点这里→
这道题暴力跑最多n/m个点(m为步长),当m较小时飞慢。考虑DP[i][j]表示从i以j步长跳到根的和,询问可达到O(1+lca)。
这样对m>sqrt(n)的暴力,<sqrt(n)的DP,复杂度O(n*sqrt(n)+n*sqrt(n)+n*logn)可以。
另外up函数是利用树剖把x往上跳y下,同一个方向跳复杂度O(logn)。
UPD:MAIN上T了233。。。
UPD:UPD:lca一不小心写成了暴力:for (;top[x]!=top[y];x=fa[x]) 这都能过也是醉了QAQ
#include<iostream>
#include<cstdio>
#include<cmath>
#define N 50005
using namespace std;
int n,m,x,y,a[N],b[N],c[N],first[N],l;
int fa[N],dep[N],size[N],Bson[N],top[N],ord[N],pos[N],cnt;
int dp[N][255];
struct Edg{int to,next;}e[N<<1];
int read(){
int x=0; char ch=getchar();
while (ch<'0' || ch>'9') ch=getchar();
while (ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar(); }
return x;
}
void link(int x,int y)
{
e[++l]=(Edg){y,first[x]};first[x]=l;
e[++l]=(Edg){x,first[y]};first[y]=l;
}
void dfs(int x)
{
dep[x]=dep[fa[x]]+1;size[x]=1;
for (int i=1,j=fa[x];i<=m;i++,j=fa[j])
dp[x][i]=dp[j][i]+a[x];
for (int i=first[x],j;i;i=e[i].next)
if ((j=e[i].to)!=fa[x])
{
fa[j]=x;dfs(j);size[x]+=size[j];
if (size[j]>size[Bson[x]]) Bson[x]=j;
}
}
void dfs(int x,int y)
{
top[x]=y;ord[x]=++cnt;pos[cnt]=x;
if (Bson[x]) dfs(Bson[x],y);
for (int i=first[x],j;i;i=e[i].next)
if ((j=e[i].to)!=fa[x]&&j!=Bson[x])
dfs(j,j);
}
int lca(int x,int y)
{
for (;top[x]!=top[y];x=fa[top[x]])
if (dep[top[x]]<dep[top[y]]) swap(x,y);
return (dep[x]<dep[y])?x:y;
}
int up(int x,int y)
{
if (dep[x]<=y) return 0;
for (;(dep[x]-dep[top[x]])<y;x=fa[top[x]])
y-=dep[x]-dep[top[x]]+1;
return pos[ord[x]-y];
}
int jump(int x,int y,int s,int p)
{
int ans=0;
if (s<m)
{
y=up(x,(dep[x]-dep[y]-p+s)/s*s);
return dp[x][s]-dp[y][s];
}
for (;dep[x]>=dep[y]+p;x=up(x,s))
ans+=a[x];
return ans;
}
int main()
{
n=read();m=sqrt(n)/7*3+1;
for (int i=1;i<=n;i++) a[i]=read();
for (int i=1;i<n;i++) x=read(),y=read(),link(x,y);
for (int i=1;i<=n;i++) b[i]=read();
for (int i=1;i<n;i++) c[i]=read();
dfs(1);dfs(1,1);
for (int i=1;i<n;i++)
{
int u=b[i],v=b[i+1],k=lca(u,v),len=dep[u]+dep[v]-2*dep[k];
int ans=jump(u,k,c[i],0);
if (len%c[i]) ans+=a[v],v=up(v,len%c[i]);
ans+=jump(v,k,c[i],1);
printf("%d\n",ans);
}
return 0;
}