Link:
Solution:
树剖模板题……
Code:
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define mid ((l+r)>>1) #define lc k<<1,l,mid #define rc k<<1|1,mid+1,r const int MAXN=1e5+10; struct edge{int to,nxt;}e[MAXN<<2]; ll seg[MAXN<<2],tag[MAXN<<2]; int n,m,x,y,head[MAXN],dep[MAXN],dat[MAXN],sz[MAXN],top[MAXN],pos[MAXN],f[MAXN],cnt,tot; void add_edge(int from,int to) {e[++tot].nxt=head[from];e[tot].to=to;head[from]=tot;} void dfs1(int x) { sz[x]=1; for(int i=head[x];i;i=e[i].nxt) { if(e[i].to==f[x]) continue; f[e[i].to]=x;dep[e[i].to]=dep[x]+1; dfs1(e[i].to);sz[x]+=sz[e[i].to]; } } void dfs2(int x,int up) { int bs=0;top[x]=up;pos[x]=++cnt; for(int i=head[x];i;i=e[i].nxt) if(e[i].to!=f[x]&&sz[e[i].to]>sz[bs]) bs=e[i].to; if(!bs) return; dfs2(bs,up); for(int i=head[x];i;i=e[i].nxt) if(e[i].to!=f[x]&&e[i].to!=bs) dfs2(e[i].to,e[i].to); } void pushdown(int k,int l,int r) { if(!tag[k]) return; tag[k<<1]+=tag[k];tag[k<<1|1]+=tag[k]; seg[k<<1]+=tag[k]*(mid-l+1); seg[k<<1|1]+=tag[k]*(r-mid); tag[k]=0; } void Update(int a,int b,int x,int k,int l,int r) { if(a<=l&&r<=b) {seg[k]+=1ll*x*(r-l+1);tag[k]+=x;return;} pushdown(k,l,r); if(a<=mid) Update(a,b,x,lc); if(b>mid) Update(a,b,x,rc); seg[k]=seg[k<<1]+seg[k<<1|1]; } ll Query(int a,int b,int k,int l,int r) { if(a<=l&&r<=b) return seg[k]; ll ret=0;pushdown(k,l,r); if(a<=mid) ret+=Query(a,b,lc); if(b>mid) ret+=Query(a,b,rc); return ret; } ll solve_query(int a,int b) { ll ret=0; while(top[a]!=top[b]) { if(dep[top[a]]<dep[top[b]]) swap(a,b); ret+=Query(pos[top[a]],pos[a],1,1,n); a=f[top[a]]; } if(pos[a]>pos[b]) swap(a,b); ret+=Query(pos[a],pos[b],1,1,n); return ret; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&dat[i]); for(int i=1;i<n;i++) scanf("%d%d",&x,&y),add_edge(x,y),add_edge(y,x); dfs1(1);dfs2(1,1); for(int i=1;i<=n;i++) Update(pos[i],pos[i],dat[i],1,1,n); while(m--) { int op,x,a;scanf("%d%d",&op,&x); if(op!=3) scanf("%d",&a); if(op==1) Update(pos[x],pos[x],a,1,1,n); else if(op==2) Update(pos[x],pos[x]+sz[x]-1,a,1,1,n); else printf("%lld ",solve_query(1,x)); } return 0; }