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