Tree Division, set the current tree Division Center for X, its sub-tree Division Center for Y, then set father[y]=x, divide and conquer can get a center of gravity tree, and the depth of the tree is Logn.
The query operation (X,D) requires only querying the sum of the nodes on the center of gravity tree on the X-to-center node. Assuming that the current node is Y, the answer that node Y can contribute is the sum of the nodes with Y as the Division center and the y distance of D-dis (x, y). Of course, there may be duplicates, and the repetition will only appear on the subtree containing the x, so it can be lost. The modification operation is similar. Complexity O (NLOGNLOGN)
Code
#include <cstdio> #include <cstring> #define N 200010#define LL long longusing namespace Std;int dp,pre[n],p[n ],tt[n],vis[n],father[n],s[n],tmp,m;int N,a,b,i,w[n],l,cnt,tot,len[n],len[n],start[n],start[n],v[n];int Deep[N], Ss[n][21],fa[n];int c[n*50];int min (int a,int b) {if (a<b) return A;return B;} int lowbit (int x) {return x& (-X);} void cc (int x,int w,int y) {while (x<=l) {c[y+x]+=w; X+=lowbit (x); }}ll sum (int x,int y) {LL ans=0; while (x>0) {ans+=c[y+x]; X-=lowbit (x); } return ans; void link (int x,int y) {dp++;p re[dp]=p[x];p [X]=dp;tt[dp]=y;} void Gao (int x) {int i; I=P[X]; while (i) {if (tt[i]!=fa[x]) {fa[tt[i]]=x; deep[tt[i]]=deep[x]+1; Gao (Tt[i]); } I=pre[i]; }}int LCA (int x,int y) {if (deep[x]>deep[y]) x^=y^=x^=y; int i; for (i=19;i>=0;i--) {if (deep[y]-deep[x]>= (1<<i)) {Y=sS[y][i]; }} if (x==y) return x; for (i=19;i>=0;i--) {if (Ss[x][i]!=ss[y][i]) {x=ss[x][i]; Y=ss[y][i]; }} return fa[x];} void getroot (int x,int fa,int sum) {int i,flag=0; I=p[x];s[x]=1; while (i) {if (!vis[tt[i]) && (TT[I]!=FA)) {getroot (tt[i],x,sum); S[x]+=s[tt[i]]; if (S[TT[I]]>SUM/2) flag=1; } I=pre[i]; } if (SUM-S[X]>SUM/2) flag=1; if (!flag) tmp=x;} void Dfs (int x,int fa,int dis) {int i; I=P[X]; if (dis>cnt) Cnt=dis; V[DIS]+=W[X]; while (i) {if ((!vis[tt[i]) && (TT[I]!=FA)) DFS (tt[i],x,dis+1); I=pre[i]; }}void Clear () {int i; for (i=1;i<=cnt;i++) v[i]=0;cnt=0;} int work (int x,int fa,int sum) {int i,root,t; Getroot (x,0,sum); root=tmp; FATHER[ROOT]=FA; I=p[root]; Vis[root]=1; while (i) {if (!vis[tt[i]]) { if (S[root]>s[tt[i]]) t=work (Tt[i],root,s[tt[i]); else T=work (Tt[i],root,sum-s[root]); ------Dist (Root,point in subtree T)--------Dfs (tt[i],0,2); len[t]=cnt; Start[t]=tot; for (int j=1;j<=cnt;j++) {l=cnt; CC (j,v[j],start[t]); } tot+=cnt; Clear (); } I=pre[i]; } vis[root]=0; --------Dist (root,all point)----------dfs (root,0,1); len[root]=cnt; Start[root]=tot; for (i=1;i<=cnt;i++) {l=cnt; CC (I,v[i],start[root]); } tot+=cnt; Clear (); return root;} LL query (int x,int d) {int y=0,z=x,t; LL ans=0; while (x) {T=lca (x,z); T=DEEP[X]+DEEP[Z]-2*DEEP[T]; L=LEN[X]; Ans+=sum (min (l,d-t+1), start[x]); if (y) {l=len[y]; Ans-=sum (min (l,d-t+1), StArt[y]); } y=x; X=FATHER[X]; } return ans; void Change (int x,int w) {int y=0,z=x,t; while (x) {T=lca (x,z); T=DEEP[X]+DEEP[Z]-2*DEEP[T]; L=LEN[X]; CC (t+1,w,start[x]); if (y) {l=len[y]; CC (T+1,w,start[y]); } y=x; X=FATHER[X]; }}int Main () {while (scanf ("%d%d", &n,&m)!=eof) {Dp=0;memset (p,0,sizeof (p)); for (i=1;i<=tot;i++) c[i]=0;tot=0; for (i=1;i<=n;i++) scanf ("%d", &w[i]); for (i=1;i<n;i++) {scanf ("%d%d", &a,&b); Link (A, b); Link (b,a); } Gao (1); for (i=1;i<=n;i++) ss[i][0]=fa[i]; for (int. h=1;h<20;h++) {for (i=1;i<=n;i++) {ss[i][h]=ss[ss[i][h-1]][h-1]; }} work (1,0,n); for (i=1;i<=m;i++) {GetChar (); Char ch; scanf ("%c%d%d", &ch,&a,&b); if (ch== '? ')) printf ("%i64d\n", query (b)); else {change (a,b-w[a]); W[a]=b; } } }}
hdu4918 Query on the subtree