裸题,树状数组区间修改+单点查询。当然要稍微讨论一下链的左右端点是否修改的情况咯。
#include<cstdio> #include<algorithm> #include<cmath> using namespace std; #define N 300001 int en,v[N<<1],first[N],next[N<<1],n; void AddEdge(const int &U,const int &V) { v[++en]=V; next[en]=first[U]; first[U]=en; } int dep[N],siz[N],fa[N],son[N],top[N],Num[N],tot; void dfs(int U,int d) { dep[U]=d; siz[U]=1; for(int i=first[U];i;i=next[i]) if(v[i]!=fa[U]) { fa[v[i]]=U; dfs(v[i],d+1); siz[U]+=siz[v[i]]; if(siz[v[i]]>siz[son[U]]) son[U]=v[i]; } } void dfs2(int U) { if(son[U]) { top[son[U]]=top[U]; Num[son[U]]=++tot; dfs2(son[U]); } for(int i=first[U];i;i=next[i]) if(v[i]!=fa[U]&&v[i]!=son[U]) { top[v[i]]=v[i]; Num[v[i]]=++tot; dfs2(v[i]); } } int SIZ[N],TOP[N],sz; void dfs3(int U) { for(int i=first[U];i;i=next[i]) if(v[i]!=fa[U]) { if(SIZ[TOP[U]]<sz) { TOP[v[i]]=TOP[U]; ++SIZ[TOP[U]]; } dfs3(v[i]); } } int lca(int U,int V) { while(U!=V) { if(TOP[U]!=TOP[V]) { if(dep[TOP[U]]<dep[TOP[V]]) swap(U,V); U=fa[TOP[U]]; } else { if(dep[U]<dep[V]) swap(U,V); U=fa[U]; } } return U; } int d[N]; void add_node(int p,const int &v){for(;p<=n;p+=(p&(-p))) d[p]+=v;} void add_range(const int &L,const int &R){add_node(L,1);if(R!=n)add_node(R+1,-1);} int query(int p){int res=0;for(;p;p-=(p&(-p)))res+=d[p];return res;} void update(int U,int V) { int f1=top[U],f2=top[V]; while(f1!=f2) { if(dep[f1]<dep[f2]) { swap(f1,f2); swap(U,V); } add_range(Num[f1],Num[U]); U=fa[f1]; f1=top[U]; } if(dep[U]>dep[V]) swap(U,V); add_range(Num[U],Num[V]); } int cnt,LL[N],RR[N]; void dfs4(int U) { LL[U]=++cnt; for(int i=first[U];i;i=next[i]) if(v[i]!=fa[U]) dfs4(v[i]); RR[U]=cnt; } int xu[N]; void work(const int &L,const int &R,const int &op) { if(op==n-1) { if(fa[L]==R||fa[R]==L) return; int LCA=lca(L,R); if(LCA==L) { for(int i=first[L];i;i=next[i]) if(v[i]!=fa[L]&&LL[R]>=LL[v[i]]&&LL[R]<=RR[v[i]]) { update(v[i],fa[R]); return; } } else if(LCA==R) { for(int i=first[R];i;i=next[i]) if(v[i]!=fa[R]&&LL[L]>=LL[v[i]]&&LL[L]<=RR[v[i]]) { update(fa[L],v[i]); return; } } else update(fa[L],fa[R]); return; } if(lca(L,R)==L) { for(int i=first[L];i;i=next[i]) if(v[i]!=fa[L]&&LL[R]>=LL[v[i]]&&LL[R]<=RR[v[i]]) { update(v[i],R); return; } } else update(fa[L],R); } int main() { int A,B; scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d",&xu[i]); for(int i=1;i<n;++i) { scanf("%d%d",&A,&B); AddEdge(A,B); AddEdge(B,A); } top[1]=1; Num[1]=++tot; dfs(1,1); dfs2(1); sz=sqrt(n); if(!sz) sz=1; for(int i=1;i<=n;i++) { SIZ[i]=1; TOP[i]=i; } dfs3(1); dfs4(1); if(n==2) { work(xu[2],xu[1],0); goto OUT; } update(xu[1],xu[2]); for(int i=2;i<n;++i) work(xu[i],xu[i+1],i); OUT:for(int i=1;i<=n;++i) printf("%d ",query(Num[i])); return 0; }