题解:树剖
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=100009;
typedef long long Lint;
int n,m;
int cntedge;
int head[maxn];
int to[maxn<<1],nex[maxn<<1];
void Addedge(int x,int y){
nex[++cntedge]=head[x];
to[cntedge]=y;
head[x]=cntedge;
}
int father[maxn],siz[maxn],depth[maxn];
Lint v[maxn];
int top[maxn],hson[maxn],idx[maxn],ref[maxn];
void Dfs(int now,int fa){
father[now]=fa;
depth[now]=depth[fa]+1;
siz[now]=1;
for(int i=head[now];i;i=nex[i]){
if(to[i]==fa)continue;
Dfs(to[i],now);
siz[now]+=siz[to[i]];
if(siz[to[i]]>siz[hson[now]])hson[now]=to[i];
}
}
int dfsclock;
void Dfs2(int now,int toppoint){
top[now]=toppoint;
idx[now]=++dfsclock;
ref[dfsclock]=now;
if(!hson[now])return;
Dfs2(hson[now],toppoint);
for(int i=head[now];i;i=nex[i]){
if(to[i]==father[now])continue;
if(to[i]==hson[now])continue;
Dfs2(to[i],to[i]);
}
}
struct SegmentTree{
int l,r;
Lint tag,sum;
}tree[maxn<<2];
void pushup(int now){
tree[now].sum=tree[now<<1].sum+tree[now<<1|1].sum;
}
void pushdown(int now){
if(tree[now].tag){
tree[now<<1].tag+=tree[now].tag;
tree[now<<1].sum+=tree[now].tag*(tree[now<<1].r-tree[now<<1].l+1);
tree[now<<1|1].tag+=tree[now].tag;
tree[now<<1|1].sum+=tree[now].tag*(tree[now<<1|1].r-tree[now<<1|1].l+1);
tree[now].tag=0;
}
}
void BuildTree(int now,int l,int r){
tree[now].l=l;tree[now].r=r;tree[now].tag=0;
if(l==r){
tree[now].sum=v[ref[l]];return;
}
int mid=(l+r)>>1;
BuildTree(now<<1,l,mid);
BuildTree(now<<1|1,mid+1,r);
pushup(now);
}
void Updatasec(int now,int ll,int rr,Lint x){
// for(int i=1;i<=1000000000;++i);
// cout<<now<<‘ ‘<<ll<<‘ ‘<<tree[now].l<<endl;
if(tree[now].l>=ll&&tree[now].r<=rr){
tree[now].tag+=x;tree[now].sum+=x*(tree[now].r-tree[now].l+1);return;
}
pushdown(now);
int mid=(tree[now].l+tree[now].r)>>1;
if(ll<=mid)Updatasec(now<<1,ll,rr,x);
if(rr>mid)Updatasec(now<<1|1,ll,rr,x);
pushup(now);
}
Lint Querysum(int now,int ll,int rr){
if(tree[now].l>=ll&&tree[now].r<=rr){
return tree[now].sum;
}
pushdown(now);
int mid=(tree[now].l+tree[now].r)>>1;
Lint ret=0;
if(ll<=mid)ret+=Querysum(now<<1,ll,rr);
if(rr>mid)ret+=Querysum(now<<1|1,ll,rr);
return ret;
}
Lint Getsum(int u){
int tu=top[u];
Lint ret=0;
while(u){
ret+=Querysum(1,idx[tu],idx[u]);
u=father[tu];tu=top[u];
}
return ret;
}
void minit(){
cntedge=dfsclock=0;
memset(head,0,sizeof(head));
memset(depth,0,sizeof(depth));
memset(hson,0,sizeof(hson));
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)scanf("%lld",&v[i]);
for(int i=1;i<=n-1;++i){
int x,y;
scanf("%d%d",&x,&y);
Addedge(x,y);
Addedge(y,x);
}
Dfs(1,0);
Dfs2(1,1);
BuildTree(1,1,n);
while(m--){
int opty,x;Lint y;
scanf("%d%d",&opty,&x);
if(opty<3)scanf("%lld",&y);
if(opty==1)Updatasec(1,idx[x],idx[x],y);
if(opty==2)Updatasec(1,idx[x],idx[x]+siz[x]-1,y);
if(opty==3)printf("%lld\n",Getsum(x));
}
return 0;
}