1 #include <cstdio> 2 #include <iostream> 3 #define ll long long 4 using namespace std; 5 const int N=2e5+10,inf=1e8; 6 int n,cnt=1,root,head[N],v[N],vis[N*2]; 7 ll q,sum,num,tot,Mx=inf,size[N],col[N],ans[N],p[N]; 8 struct edge { int to,from; }e[N*2]; 9 void clear(int x,int fa) { p[v[x]]=col[v[x]]=0; for (int i=head[x];i;i=e[i].from) if (!vis[i]&&e[i].to!=fa) clear(e[i].to,x); } 10 void insert(int x,int y) 11 { 12 e[++cnt].to=y,e[cnt].from=head[x],head[x]=cnt; 13 e[++cnt].to=x,e[cnt].from=head[y],head[y]=cnt; 14 } 15 void dfs1(int x,int fa) 16 { 17 size[x]=1,p[v[x]]++; 18 for (int i=head[x];i;i=e[i].from) if (e[i].to!=fa&&!vis[i]) dfs1(e[i].to,x),size[x]+=size[e[i].to]; 19 if (p[v[x]]==1) sum+=size[x],col[v[x]]+=size[x]; 20 p[x[v]]--; 21 } 22 void dfs2(int x,int fa) 23 { 24 p[v[x]]++; 25 if (p[v[x]]==1) sum-=col[v[x]],num++; 26 ans[x]+=sum+num*q; 27 for (int i=head[x];i;i=e[i].from) if (!vis[i]&&e[i].to!=fa) dfs2(e[i].to,x); 28 if (p[v[x]]==1) sum+=col[v[x]],num--; 29 p[v[x]]--; 30 } 31 void findroot(int x,int fa) 32 { 33 size[x]=1; ll mx=0; 34 for (int i=head[x];i;i=e[i].from) if (e[i].to!=fa&&!vis[i]) findroot(e[i].to,x),size[x]+=size[e[i].to],mx=max(mx,size[e[i].to]); 35 mx=max(mx,tot-size[x]); 36 if (mx<Mx) Mx=mx,root=x; 37 } 38 void change(int x,int fa,int k) 39 { 40 p[v[x]]++; 41 for (int i=head[x];i;i=e[i].from) if (e[i].to!=fa&&!vis[i]) change(e[i].to,x,k); 42 if (p[v[x]]==1) sum+=(ll)size[x]*k,col[v[x]]+=(ll)size[x]*k; 43 p[v[x]]--; 44 } 45 void solve(int x,int fa) 46 { 47 dfs1(x,fa),ans[x]+=sum-col[v[x]]+size[x]; 48 for (int i=head[x];i;i=e[i].from) if (!vis[i]&&e[i].to!=fa) 49 p[v[x]]++,sum-=size[e[i].to],col[v[x]]-=size[e[i].to],change(e[i].to,x,-1),p[v[x]]--,q=size[x]-size[e[i].to],dfs2(e[i].to,x),p[v[x]]++,sum+=size[e[i].to],col[v[x]]+=size[e[i].to],change(e[i].to,x,1),p[v[x]]--; 50 sum=0,num=0,clear(x,fa); 51 for (int i=head[x];i;i=e[i].from) if (!vis[i]&&e[i].to!=fa) vis[i]=1,vis[i^1]=1,tot=size[e[i].to],Mx=inf,findroot(e[i].to,x),solve(root,0); 52 } 53 int main() 54 { 55 scanf("%d",&n); 56 for (int i=1;i<=n;i++) scanf("%d",&v[i]); 57 for (int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),insert(x,y); 58 tot=n,findroot(1,0),solve(root,0); 59 for (int i=1;i<=n;i++) printf("%lld\n",ans[i]); 60 }
原文:https://www.cnblogs.com/Comfortable/p/11329694.html