题解:树上差分就可以了
论看懂题意的重要性
最后-1的时候处理错了,WA了几发
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn=600009; const int Inf=1000000000; int n,m; int a[maxn]; int cntedge; int head[maxn]; int to[maxn<<1],nex[maxn<<1]; void Addedge(int x,int y){ nex[++cntedge]=head[x]; to[cntedge]=y; head[x]=cntedge; } int siz[maxn]; int dep[maxn]; int f[maxn][20]; void Dfs(int now,int fa){ f[now][0]=fa; dep[now]=dep[fa]+1; siz[now]=1; for(int i=head[now];i;i=nex[i]){ if(to[i]==fa)continue; Dfs(to[i],now); siz[now]+=siz[to[i]]; } } void LCAinit(){ for(int j=1;j<=19;++j){ for(int i=1;i<=n;++i){ f[i][j]=f[f[i][j-1]][j-1]; } } } int Getlca(int u,int v){ if(dep[u]<dep[v])swap(u,v); for(int j=19;j>=0;--j){ if(dep[f[u][j]]>=dep[v])u=f[u][j]; } if(u==v)return u; for(int j=19;j>=0;--j){ if(f[u][j]!=f[v][j]){ u=f[u][j];v=f[v][j]; } } return f[u][0]; } int g[maxn]; void Dp(int x,int fa){ for(int i=head[x];i;i=nex[i]){ if(to[i]==fa)continue; Dp(to[i],x); g[x]+=g[to[i]]; } } int main(){ scanf("%d",&n); for(int i=1;i<=n;++i)scanf("%d",&a[i]); for(int i=1;i<=n-1;++i){ int x,y; scanf("%d%d",&x,&y); Addedge(x,y); Addedge(y,x); } Dfs(1,0); LCAinit(); for(int i=1;i<n;++i){ int lca=Getlca(a[i],a[i+1]); g[a[i]]++;g[a[i+1]]++; g[lca]--;g[f[lca][0]]--; } Dp(1,0); for(int i=1;i<=n;++i){ if(i==a[1])printf("%d ",g[i]); else printf("%d ",g[i]-1); } return 0; }