BZOJ 4034 T2 樹鏈剖分解決子樹問題

2021-07-15 23:08:13 字數 1335 閱讀 5037

樹鏈剖分有這樣乙個性質,即在剖完之後每個結點下面子樹的編號一定是連續的,那麼基於這一點,我們記錄每個結點的區間就能解決子樹更新問題

dfs序也可以解決子樹問題,但是這裡需要計算乙個貢獻值,結點的層數不好處理。

#include#include#include#includeusing namespace std;

#define maxn 200004

int fir[maxn],nex[maxn],v[maxn],e_max;

int in[maxn],out[maxn],son[maxn],fa[maxn],siz[maxn],deep[maxn],top[maxn],tot;

long long val[maxn],val1[maxn],sum[2*maxn],tag[2*maxn];

void init_()

void add_edge(int s,int t)

void dfs1(int k,int pre,int d)

void pushdown(int k,int l,int r)

void update(int val,int s,int t,int l,int r,int k)

pushdown(k,l,r);

int mid=l+r>>1;

if(t<=mid) update(val,s,t,l,mid,k<<1);

else if(s>mid) update(val,s,t,mid+1,r,k<<1|1);

else update(val,s,mid,l,mid,k<<1),update(val,mid+1,t,mid+1,r,k<<1|1);

sum[k]=sum[k<<1]+sum[k<<1|1];

}long long query(int s,int t,int l,int r,int k)

pushdown(k,l,r);

int mid=l+r>>1;

if(t<=mid) return query(s,t,l,mid,k<<1);

else if(s>mid) return query(s,t,mid+1,r,k<<1|1);

else return query(s,mid,l,mid,k<<1)+query(mid+1,t,mid+1,r,k<<1|1);

}long long query(int s,int t)

int main()

{ int n,m;

while(scanf("%d%d",&n,&m)!=eof)

{init_();

for(int i=1;i<=n;i++) scanf("%lld",&val[i]);

for(int i=1;i

bzoj4034 T2 樹鏈剖分 樹狀陣列

一種明顯的做法是直接樹鏈剖分然後用區間修改區間查詢樹狀陣列 我寫的這種 或者線段樹來維護吧。這樣做是o nlog 2n 的。但是還可以做到o nlogn 首先可以發現它是單點鏈上查詢,那麼可以考慮用差分的思想,或者考慮將單點修改直接變成區間修改然後就只用單點簡單查詢了。首先考慮單點修改,這種操作只對...

bzoj4034 樹鏈剖分

time limit 10 sec memory limit 256 mb submit 7576 solved 2597 submit status discuss 有一棵點數為 n 的樹,以點 1 為根,且樹點有邊權。然後有 m 個 操作,分為三種 操作 1 把某個節點 x 的點權增加 a 操作...

11 03T2 樹鏈剖分

給你一棵樹,每次詢問樹上兩條鏈是否有交點。第一行n,表示n個結點 第二行開始n 1行倆個 數x y,表示x,y有一條邊 接下來q,表示q個詢問 接下來q行四個數a b c d,詢問a到b的鏈是否與c到d的鏈有交點 輸出q行 yes或no sample input 輸入1 1 21 3 2 42 5 ...