Description
给定一棵n个点的树,树上每条边的长度都为1,第i个点的权值为a[i]。
Byteasar想要走遍这整棵树,他会按照某个1到n的全排列b走n-1次,第i次他会从b[i]点走到b[i+1]点,并且这一次的步伐大小为c[i]。
对于一次行走,假设起点为x,终点为y,步伐为k,那么Byteasar会从x开始,每步往前走k步,如果最后不足k步就能到达y,那么他会一步走到y。
请帮助Byteasar统计出每一次行走时经过的所有点的权值和。
Input
第一行包含一个正整数n(2<=n<=50000)。表示节点的个数。
第二行包含n个正整数,其中第i个数为a[i](1<=a[i]<=10000),分别表示每个点的权值。
接下来n-1行,每行包含两个正整数u,v(1<=u,v<=n),表示u与v之间有一条边。
接下来一行包含n个互不相同的正整数,其中第i个数为b[i](1<=b[i]<=n),表示行走路线。
接下来一行包含n-1个正整数,其中第i个数为c[i](1<=c[i]<n),表示每次行走的步伐大小。
Output
包含n-1行,每行一个正整数,依次输出每次行走时经过的所有点的权值和
对<sqrt(n)的步长,预处理从每个点向上以每个步长走到根的权值和
对于更大的步长可以暴力计算
#include<bits/stdc++.h> const int N=50007; char buf[N*50],*ptr=buf-1; int _(){ int x=0,c=*++ptr; while(c<48)c=*++ptr; while(c>47)x=x*10+c-48,c=*++ptr; return x; } int n,a[N],b[N],md=1,B,sum[N][233]; int es[N*2],enx[N*2],e0[N],ep=2; int fa[N],sz[N],dep[N],son[N],top[N],id[N],idr[N],idp=0; void maxs(int&a,int b){if(a<b)a=b;} void f1(int w,int pa){ dep[w]=dep[fa[w]=pa]+1; maxs(md,dep[w]); sz[w]=1; for(int i=e0[w];i;i=enx[i]){ int u=es[i]; if(u!=pa){ f1(u,w); sz[w]+=sz[u]; if(sz[u]>sz[son[w]])son[w]=u; } } } void f2(int w,int tp){ top[w]=tp; idr[id[w]=++idp]=w; if(son[w])f2(son[w],tp); for(int i=e0[w];i;i=enx[i]){ int u=es[i]; if(u!=fa[w]&&u!=son[w])f2(u,u); } } int lca(int x,int y){ int a=top[x],b=top[y]; while(a!=b){ if(dep[a]<dep[b])y=fa[b],b=top[y]; else x=fa[a],a=top[x]; } return dep[x]<dep[y]?x:y; } int up(int x,int d){ if(d>=dep[x])return 0; int y=dep[x]-d,a=top[x]; while(dep[a]>y)x=fa[a],a=top[x]; return idr[id[x]-dep[x]+y]; } int cal(int x,int y,int v){ if(dep[x]<=dep[y])return 0; int s=0; if(v<=B){ s+=sum[x][v]; int r=v-(dep[x]-dep[y])%v; s-=sum[r==v?y:up(y,r)][v]; }else{ while(dep[x]>dep[y])s+=a[x],x=up(x,v); } return s; } void calc(int x,int y,int v){ int z=lca(x,y),r=(dep[x]+dep[y]-dep[z]*2)%v,ans=0; ans+=cal(x,z,v); if(r){ ans+=a[y]; y=up(y,r); } ans+=cal(y,fa[z],v); printf("%d ",ans); } void f3(int w){ for(int i=1;i<=B;++i)sum[w][i]=sum[up(w,i)][i]+a[w]; for(int i=e0[w];i;i=enx[i]){ int u=es[i]; if(u!=fa[w])f3(u); } } int main(){ buf[fread(buf,1,sizeof(buf),stdin)]=0; n=_(); for(int i=1;i<=n;++i)a[i]=_(); for(int i=1,a,b;i<n;++i){ a=_();b=_(); es[ep]=b;enx[ep]=e0[a];e0[a]=ep++; es[ep]=a;enx[ep]=e0[b];e0[b]=ep++; } f1(1,0);f2(1,1); B=sqrt(md+1)*0.7+1; f3(1); for(int i=1;i<=n;++i)b[i]=_(); for(int i=1;i<n;++i)calc(b[i],b[i+1],_()); return 0; }