BZOJ4034_树上操作_KEY
这道题可以树链剖分+线段树。
其他操作模板,第二个操作只需要将x~x+size[x]-1区间加值即可。
code:
#include <cstdio> #include <cstring> using namespace std; int read(){ char c;while(c=getchar(),(c<'0'||c>'9')&&c!='-'); int x=0,y=1;c=='-'?y=-1:x=c-'0'; while(c=getchar(),c>='0'&&c<='9')x=x*10+c-'0'; return x*y; } const int Maxn=100005; int N,Q,A[Maxn]; int head[Maxn],nxt[Maxn<<1],to[Maxn<<1],Cnt; void Add(int x,int y){ to[Cnt]=y; nxt[Cnt]=head[x]; head[x]=Cnt; Cnt++; } int Son[Maxn],Size[Maxn],f[Maxn]; int Dep[Maxn],Dfn[Maxn],Top[Maxn]; int C; void Find(int Now,int Deep,int Bef){ f[Now]=Bef,Dep[Now]=Deep,Size[Now]=1; for(int i=head[Now];i!=-1;i=nxt[i]){ if(to[i]==f[Now])continue; Find(to[i],Deep+1,Now); Size[Now]+=Size[to[i]]; if(Size[to[i]]>Size[Son[Now]]) Son[Now]=to[i]; } return ; } void Fs(int Now,int Tp){ Dfn[Now]=++C,Top[Now]=Tp; if(Son[Now])Fs(Son[Now],Tp); for(int i=head[Now];i!=-1;i=nxt[i]){ if(to[i]==Son[Now]||to[i]==f[Now])continue; Fs(to[i],to[i]); } return ; } long long Seg[Maxn<<2],Ade[Maxn<<2]; void Up(int x){Seg[x]=Seg[x<<1]+Seg[x<<1|1];} void Down(int x,long long l,long long r){ if(!Ade[x])return ; Seg[x<<1]+=Ade[x]*l; Seg[x<<1|1]+=Ade[x]*r; Ade[x<<1]+=Ade[x]; Ade[x<<1|1]+=Ade[x]; Ade[x]=0; } void Updata(int Node,int L,int R,int Ul,int Ur,long long Val){ if(Ul<=L&&Ur>=R){ Seg[Node]+=Val*(R-L+1); Ade[Node]+=Val; return ; } int Mid=L+R>>1; Down(Node,Mid-L+1,R-Mid); if(Mid>=Ul)Updata(Node<<1,L,Mid,Ul,Ur,Val); if(Mid< Ur)Updata(Node<<1|1,Mid+1,R,Ul,Ur,Val); Up(Node); } long long Query(int Node,int L,int R,int Ql,int Qr){ if(Ql<=L&&Qr>=R)return Seg[Node]; int Mid=L+R>>1; Down(Node,Mid-L+1,R-Mid); long long Ans=0; if(Mid>=Ql)Ans+=Query(Node<<1,L,Mid,Ql,Qr); if(Mid< Qr)Ans+=Query(Node<<1|1,Mid+1,R,Ql,Qr); return Ans; } long long G(int Node){ long long Ans=0; while(Top[Node]){ Ans+=Query(1,1,N,Dfn[Top[Node]],Dfn[Node]); Node=f[Top[Node]]; } return Ans; } int main() { memset(head,-1,sizeof head); N=read(),Q=read(); for(int i=1;i<=N;i++)A[i]=read(); for(int i=1;i<N;i++){ int x=read(),y=read(); Add(x,y),Add(y,x); } Find(1,1,0),Fs(1,1); for(int i=1;i<=N;i++) Updata(1,1,N,Dfn[i],Dfn[i],A[i]); for(int i=1;i<=Q;i++){ int Type=read(),x=read(); if(Type==1)Updata(1,1,N,Dfn[x],Dfn[x],read()); if(Type==2)Updata(1,1,N,Dfn[x],Dfn[x]+Size[x]-1,read()); if(Type==3)printf("%lld\n",G(x)); } return 0; }