「HAOI2015」树上操作 发表于 2019-04-06 | 分类于 树链剖分 | | 浏览量: 次 赤裸裸的树剖啊。 传送门洛谷P3178 BZOJ4034 题解裸的树链剖分,没啥好说的。直接搞就好了 代码123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124#include<cstdio>using namespace std;typedef long long LL;const int maxn=100005;int n,m,tot,lnk[maxn],son[maxn*2],w[maxn],nxt[maxn*2],idx,siz[maxn],wson[maxn],fa[maxn],top[maxn],seg[maxn],rev[maxn];LL ans;inline int read(){ int ret=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();} while(ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();} return ret*f;}struct SegmentTree{ struct Node{LL Sum,Tag;}Tree[maxn*4]; void PushUp(int rt){Tree[rt].Sum=Tree[rt*2].Sum+Tree[rt*2+1].Sum;} void PushDown(int rt,int LC,int RC) { if(!Tree[rt].Tag) return; Tree[rt*2].Sum+=Tree[rt].Tag*LC; Tree[rt*2+1].Sum+=Tree[rt].Tag*RC; Tree[rt*2].Tag+=Tree[rt].Tag; Tree[rt*2+1].Tag+=Tree[rt].Tag; Tree[rt].Tag=0; } void Build(int L=1,int R=n,int rt=1) { if(L==R){Tree[rt].Sum=w[rev[L]];return;} int M=(L+R)>>1; Build(L,M,rt*2); Build(M+1,R,rt*2+1); PushUp(rt); } void RangeUpdate(int LL,int RR,int delta,int L=1,int R=n,int rt=1) { if(LL<=L&&R<=RR) { Tree[rt].Sum+=(long long)delta*(R-L+1); Tree[rt].Tag+=delta; return; } int M=(L+R)/2; PushDown(rt,M-L+1,R-M); if(LL<=M) RangeUpdate(LL,RR,delta,L,M,rt*2); if(M<RR) RangeUpdate(LL,RR,delta,M+1,R,rt*2+1); PushUp(rt); } LL QueryRange(int LL,int RR,int L=1,int R=n,int rt=1) { if(LL<=L&&R<=RR) return Tree[rt].Sum; int M=(L+R)/2;::LL ret=0; PushDown(rt,M-L+1,R-M); if(LL<=M) ret+=QueryRange(LL,RR,L,M,rt*2); if(M<RR) ret+=QueryRange(LL,RR,M+1,R,rt*2+1); return ret; }}T;inline void add_e(int x,int y){tot++;son[tot]=y;nxt[tot]=lnk[x];lnk[x]=tot;}void DFS1(int now){ siz[now]=1; for(int i=lnk[now];i;i=nxt[i]) { if(son[i]==fa[now]) continue; fa[son[i]]=now; DFS1(son[i]); siz[now]+=siz[son[i]]; } for(int i=lnk[now];i;i=nxt[i]) if(son[i]!=fa[now]&&siz[son[i]]>siz[wson[now]]) wson[now]=son[i];}void DFS2(int now){ seg[now]=++idx;rev[seg[now]]=now; if(now==1) top[now]=1; if(wson[now]) { top[wson[now]]=top[now]; DFS2(wson[now]); } for(int i=lnk[now];i;i=nxt[i]) { if(son[i]==fa[now]||son[i]==wson[now]) continue; top[son[i]]=son[i]; DFS2(son[i]); }}int main(){ n=read();m=read(); for(int i=1;i<=n;i++) w[i]=read(); for(int i=1;i<n;i++) { int a=read(),b=read(); add_e(a,b);add_e(b,a); } DFS1(1);DFS2(1);T.Build(); while(m--) { int opt=read(),x=read(); if(opt==1) { int a=read(); T.RangeUpdate(seg[x],seg[x],a); } else if(opt==2) { int a=read(); T.RangeUpdate(seg[x],seg[x]+siz[x]-1,a); } else { ans=0; while(x>0) { ans+=T.QueryRange(seg[top[x]],seg[x]); x=fa[top[x]]; } printf("%lld\n",ans); } } return 0;}