分开维护树的入栈序和出栈序,用两棵线段树。回答时就是用一颗的减去另一棵的。
#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\n",Query(0,Ls[x],1,1,n)-((!Map[x])?0:Query(1,oRs[Map[x]],1,1,n)));
}
return 0;
}