分开维护树的入栈序和出栈序,用两棵线段树。回答时就是用一颗的减去另一棵的。
#include<cstdio> #include<algorithm> using namespace std; typedef long long ll; #define N 100001 ll sumv[2][N<<2],delta[2][N<<2]; void pushdown(int o,int rt,int sz) { if(delta[o][rt]) { delta[o][rt<<1]+=delta[o][rt]; delta[o][rt<<1|1]+=delta[o][rt]; sumv[o][rt<<1]+=delta[o][rt]*(ll)(sz-(sz>>1)); sumv[o][rt<<1|1]+=delta[o][rt]*(ll)(sz>>1); delta[o][rt]=0; } } void Update(int o,int ql,int qr,int v,int rt,int l,int r) { if(ql<=l&&r<=qr) { delta[o][rt]+=(ll)v; sumv[o][rt]+=(ll)v*(ll)(r-l+1); return; } int m=(l+r>>1); pushdown(o,rt,r-l+1); if(ql<=m) Update(o,ql,qr,v,rt<<1,l,m); if(m<qr) Update(o,ql,qr,v,rt<<1|1,m+1,r); sumv[o][rt]=sumv[o][rt<<1]+sumv[o][rt<<1|1]; } ll Query(int o,int qr,int rt,int l,int r) { if(r<=qr) return sumv[o][rt]; int m=(l+r>>1); ll res=0; pushdown(o,rt,r-l+1); res+=Query(o,qr,rt<<1,l,m); if(m<qr) res+=Query(o,qr,rt<<1|1,m+1,r); return res; } int n,m,a[N]; int e,v[N<<1],first[N],next[N<<1]; void AddEdge(int U,int V) { v[++e]=V; next[e]=first[U]; first[U]=e; } int Ls[N],Rs[N],oLs[N],oRs[N],xu[N<<1]; int tot,to2,to3; void dfs(int U,int Fa) { Ls[U]=++tot; xu[++to3]=U; for(int i=first[U];i;i=next[i]) if(v[i]!=Fa) dfs(v[i],U); Rs[U]=tot; xu[++to3]=U; oRs[U]=oLs[U]=++to2; } void df2(int U,int Fa) { for(int i=first[U];i;i=next[i]) if(v[i]!=Fa) { df2(v[i],U); oLs[U]=min(oLs[U],oLs[v[i]]); } } bool hav[N]; int Map[N]; int main() { int x,y,op; scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) scanf("%d",&a[i]); for(int i=1;i<n;++i) { scanf("%d%d",&x,&y); AddEdge(x,y); AddEdge(y,x); } dfs(1,0); df2(1,0); int last=0; for(int i=1;i<=to3;++i) if(!hav[xu[i]]) { Map[xu[i]]=last; hav[xu[i]]=1; } else last=xu[i]; for(int i=1;i<=n;++i) { Update(0,Ls[i],Ls[i],a[i],1,1,n); Update(1,oRs[i],oRs[i],a[i],1,1,n); } for(;m;--m) { scanf("%d%d",&op,&x); if(op==1) { scanf("%d",&y); Update(0,Ls[x],Ls[x],y,1,1,n); Update(1,oRs[x],oRs[x],y,1,1,n); } else if(op==2) { scanf("%d",&y); Update(0,Ls[x],Rs[x],y,1,1,n); Update(1,oLs[x],oRs[x],y,1,1,n); } else printf("%I64d ",Query(0,Ls[x],1,1,n)-((!Map[x])?0:Query(1,oRs[Map[x]],1,1,n))); } return 0; }