题解:树剖
#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; }