gdoi2017第四輪模擬:對於一棵樹,q個操作可以新增節點或改變乙個點的權值,或詢問整棵樹的帶權重心,強制**1≤q≤3105。
考慮如何找帶權重心,顯然是每次往最大權的子樹走,條件是這個子樹的權2大於整棵樹的權值和。
那麼就很明顯了,我們要做的是維護以每個點為根的子樹的權值和,以及每個點的兒子中的最大權。
由於一條鏈上的資訊更改會影響很多點,那麼我們可以用lct,維護的是以每個點為根的子樹的權值和,以及每個點的虛邊兒子中的最大權。
對於後者,可以對每個點開乙個set,在斷開和連起來的時候都更改一下就好了
找答案的時候,我們考慮從根節點開始,每次在鏈上二分出要走到的位置,然後再走到他的最大兒子。
這樣的複雜度貌似很懸?
我們這樣做其實相當於從根走到重心,這根重心做一次access的複雜度是一樣的,所以總的時間複雜度是o(nlog2n)
#include
#include
#include
#include
#include
#include
#include
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
typedef long long ll;
typedef double db;
int get()
int s=ch-'0';
while(ch=getchar(),ch>='0'&&ch<='9')s=s*10+ch-'0';
return s;
}const int n = 300010;
struct light_edgetree[n];
int fa[n];
int n;
int m;
int a[n],k;
ll val[n];
int w[n];
ll maxll(ll x,ll y)
void update(int x)
void down(int x)
y=tree[x].s[1];
if (y)
tree[x].ad=0;
}update(x);
}int pd(int x)
void clear(int x)
void rotate(int x)
void splay(int x)
rotate(x);
}}int get1st(int x)
void put_light(int x,int y,ll sum)
}void del_light(int x,int y,ll sum)
else val[x]=w[x]=0;
}void split(int x,int y)
void merge(int x,int y)
void access(int x)
}void walk(int &x)
int kth(int x,int k)
int getw(int x)
int ans;
void getans(){
int x=1;
ans=1;
ll tv=1e+13;
bool bz=1;
while(bz&&x){
bz=0;
splay(x);
int w=getw(x);
splay(w);
int u=get1st(tree[w].s[1]);
ll tmp=maxll(val[w],maxll(tree[u].sum,tree[1].sum-tree[w].sum));
if (tmp
gdoi2017四輪模擬最後總結
由於太急導致題目沒看清楚,碼了錯的暴力,這個非常虧,做了無用功。mle不用說,太貪心想打多點暴力分,結果空間開大了,直接爆零得不償失。想法不夠精簡,導致實現起來十分困難,浪費的時間沒拿到應有的分。細節沒考慮好,明明注意到了細節,處理了卻沒處理好。有想法卻看漏條件,導致出了偏差,想到並實現了錯誤的方法...
GDOI2017模擬第二輪 4 15 4 17
round 1 4.15 今天發揮。不好不差吧,一般般,基本沒有失分,但是相對的也沒有爆分。原以為t3可以搞一波大事情結果wa了,其實我拍出錯了但是並不知道 錯了,肉眼調不出錯,又是大資料,我小資料全對,就是大資料炸了,很不爽。第乙個小時拿來看題目。感覺t1是神題,先放著。t2的話,打表的分數挺多啊...
GDOI2017模擬第二輪總結
這場一上來就開始想t1,想了一段時間還是沒什麼思路,然後剛t3,感覺bitset可做。但是後面發現bitset只能處理空降而不能處理移動,於是就趕緊先打了乙個60分暴力。t2打表水了60,然後t4打了乙個20分暴力。還剩下1.5h回過頭來做t1,打了一半發現有問題,最後只好打30分暴力。主要是t1思...