题解:dfs序+树链剖分
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define N 200003 #define LL long long using namespace std; int n,m,t,tot,sz; LL tr[N*4],delta[N*4]; int point[N],next[N],v[N],belong[N],size[N],son[N],fa[N],deep[N]; int pos[N],l[N],r[N]; void add(int x,int y) { tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y; tot++; next[tot]=point[y]; point[y]=tot; v[tot]=x; } void dfs(int x,int f) { size[x]=1; for (int i=point[x];i;i=next[i]) if (v[i]!=f) { deep[v[i]]=deep[x]+1; dfs(v[i],x); fa[v[i]]=x; size[x]+=size[v[i]]; if (size[v[i]]>size[son[x]]) son[x]=v[i]; } } void build(int k,int chain) { belong[k]=chain; pos[k]=++sz; l[k]=sz; r[k]=sz; if (!son[k]) return; build(son[k],chain); for (int i=point[k];i;i=next[i]) if (v[i]!=fa[k]&&v[i]!=son[k]) build(v[i],v[i]); r[k]=sz; } void pushdown(int now,int l,int r) { if (!delta[now]) return; delta[now<<1]+=delta[now]; delta[now<<1|1]+=delta[now]; int mid=(l+r)/2; tr[now<<1]+=(LL)(mid-l+1)*delta[now]; tr[now<<1|1]+=(LL)(r-mid)*delta[now]; delta[now]=0; } LL query(int now,int l,int r,int ll,int rr) { if (l>=ll&&r<=rr) return tr[now]; pushdown(now,l,r); int mid=(l+r)/2; LL ans=0; if (ll<=mid) ans+=query(now<<1,l,mid,ll,rr); if (rr>mid) ans+=query(now<<1|1,mid+1,r,ll,rr); return ans; } void change(int now,int l,int r,int ll,int rr,LL v) { if (l>=ll&&r<=rr){ tr[now]+=(LL)v*(r-l+1); delta[now]+=v; return; } pushdown(now,l,r); int mid=(l+r)/2; if (ll<=mid) change(now<<1,l,mid,ll,rr,v); if (rr>mid) change(now<<1|1,mid+1,r,ll,rr,v); tr[now]=tr[now<<1]+tr[now<<1|1]; } void solve(int x,int y,LL v) { while (belong[x]!=belong[y]) { if (deep[belong[x]]<deep[belong[y]]) swap(x,y); change(1,1,n,pos[belong[x]],pos[x],v); x=fa[belong[x]]; } if (deep[x]>deep[y]) swap(x,y); change(1,1,n,pos[x],pos[y],v); } int main() { freopen("a.in","r",stdin); scanf("%d",&n); for (int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); x++; y++; add(x,y); } deep[1]=1; dfs(1,0); build(1,1); scanf("%d",&t); for (int i=1;i<=t;i++) { char s[10]; scanf("%s",s); if (s[0]=='A'){ int x,y; LL z; scanf("%d%d%I64d",&x,&y,&z); x++; y++; solve(x,y,z); } else{ int x; scanf("%d",&x); x++; printf("%I64d\n",query(1,1,n,l[x],r[x])); } } }