dsu on tree模板题
暴力显然\(O(n^2)\) O(TLE)
我们发现,在 对某个节点的树做统计 前,最后一个儿子的那棵子树统计不用清空
并且,这个不用清空的儿子size越大,显然越优挑size最大的来就行
O(nlogn)
#include<iostream>
#include<cstdio>
#define LL long long
using namespace std;
int n,x,y,tot,mx,Son;
LL nowans;
const int N=100010;
int col[N],head[N],to[N<<1],nt[N<<1],siz[N],son[N],cnt[N];
LL ans[N];
void add(int f,int t)
{
to[++tot]=t;nt[tot]=head[f];head[f]=tot;
}
void dfs1(int x,int fa)
{
siz[x]=1;
for(int i=head[x];i;i=nt[i])
if(to[i]!=fa)
{
dfs1(to[i],x);
siz[x]+=siz[to[i]];
if(siz[to[i]]>siz[son[x]])son[x]=to[i];
}
}
void ADD(int x,int fa,int val)
{
cnt[col[x]]+=val;
if(cnt[col[x]]>mx)mx=cnt[col[x]],nowans=col[x];
else if(cnt[col[x]]==mx)nowans+=col[x];
for(int i=head[x];i;i=nt[i])
if(to[i]!=fa&&to[i]!=Son)ADD(to[i],x,val);
}
void dfs2(int x,int fa,int opt)
{
for(int i=head[x];i;i=nt[i])
if(to[i]!=fa&&to[i]!=son[x])dfs2(to[i],x,0);
if(son[x])dfs2(son[x],x,1),Son=son[x];
ADD(x,fa,1);Son=0;ans[x]=nowans;
if(!opt)ADD(x,fa,-1),nowans=0,mx=0;
}
int main()
{
cin>>n;
for(int i=1;i<=n;++i)scanf("%d",&col[i]);;
for(int i=1;i<n;++i)
{
scanf("%d%d",&x,&y);
add(x,y);add(y,x);
}
dfs1(1,0);dfs2(1,0,1);
for(int i=1;i<=n;++i)printf("%lld ",ans[i]);
return 0;
}