学习一下$dsu on tree$。。
这个东西可以处理很多无修改子树问题,复杂度通常为$O(nlogn)$。
主要操作是:我们先把整棵树链剖一下,然后每次先递归轻儿子,再递归重儿子。
对于每棵子树,我们暴力加入整棵子树的贡献。如果是重儿子的子树则另外处理:加入贡献时不考虑加重儿子所在的子树,而在消除贡献时也不消除重儿子的子树,直到它成为某个点的轻儿子的子树的一部分时再消除贡献。
复杂度:因为每个轻儿子最多被加入$O(logn)$次(递归轻儿子时$size$至少$/2$),每条重链最多只会被加入$O(logn)$次,所以复杂度是$O(nlogn)$的。
说得有点玄学,还是看看代码吧。。
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 #include <cstdlib> 6 #include <cstdio> 7 #include <vector> 8 #include <cmath> 9 #include <queue> 10 #include <stack> 11 #include <map> 12 #include <set> 13 #define inf (1<<30) 14 #define N (200010) 15 #define il inline 16 #define RG register 17 #define ll long long 18 19 using namespace std; 20 21 struct edge{ int nt,to; }g[N<<1]; 22 23 int head[N],col[N],son[N],sz[N],c[N],n,num,Mx,flag; 24 ll ans[N],Sum; 25 26 il int gi(){ 27 RG int x=0,q=1; RG char ch=getchar(); 28 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 29 if (ch=='-') q=-1,ch=getchar(); 30 while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); 31 return q*x; 32 } 33 34 il void insert(RG int from,RG int to){ 35 g[++num]=(edge){head[from],to},head[from]=num; return; 36 } 37 38 il void dfs1(RG int x,RG int p){ 39 sz[x]=1; RG int v; 40 for (RG int i=head[x];i;i=g[i].nt){ 41 v=g[i].to; if (v==p) continue; 42 dfs1(v,x),sz[x]+=sz[v]; 43 if (sz[son[x]]<=sz[v]) son[x]=v; 44 } 45 return; 46 } 47 48 il void add(RG int x,RG int p,RG int val){ 49 col[c[x]]+=val; RG int v; 50 if (Mx<col[c[x]]) Mx=col[c[x]],Sum=c[x]; 51 else if (Mx==col[c[x]]) Sum+=c[x]; 52 for (RG int i=head[x];i;i=g[i].nt){ 53 v=g[i].to; if (v==p || v==flag) continue; 54 add(v,x,val); 55 } 56 return; 57 } 58 59 il void dfs2(RG int x,RG int p,RG int fg){ 60 RG int v; 61 for (RG int i=head[x];i;i=g[i].nt){ 62 v=g[i].to; if (v!=p && v!=son[x]) dfs2(v,x,1); 63 } 64 if (son[x]) dfs2(son[x],x,0),flag=son[x]; 65 add(x,p,1),flag=0,ans[x]=Sum; 66 if (fg) add(x,p,-1),Mx=Sum=0; return; 67 } 68 69 int main(){ 70 #ifndef ONLINE_JUDGE 71 freopen("600E.in","r",stdin); 72 freopen("600E.out","w",stdout); 73 #endif 74 n=gi(); 75 for (RG int i=1;i<=n;++i) c[i]=gi(); 76 for (RG int i=1,u,v;i<n;++i) 77 u=gi(),v=gi(),insert(u,v),insert(v,u); 78 dfs1(1,0),dfs2(1,0,1); 79 for (RG int i=1;i<=n;++i) printf("%I64d ",ans[i]); 80 return 0; 81 }