这题和[Vani有约会]雨天的尾巴 有些神似的地方 算是线段树合并的模板题把 每个结点维护一颗线段树 线段树维护颜色出现个数 以及编号和 pushup要写好 想清楚 最后dfs合并起来就行了
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
typedef long long ll;
#define ls T[rt].l
#define rs T[rt].r
ll ans[N];
int h[N],to[N<<1],nex[N<<1],cur,rt[N],tot;
struct tree{
int ct,l,r;
ll sum;
}T[N*50];
void add_edge(int x,int y){
to[++cur]=y;nex[cur]=h[x];h[x]=cur;
}
void pushup(int rt){
if(T[ls].ct==T[rs].ct){
T[rt].sum=T[ls].sum+T[rs].sum;
T[rt].ct=T[ls].ct;
}else{
if(T[ls].ct>T[rs].ct) T[rt].sum=T[ls].sum,T[rt].ct=T[ls].ct;
else T[rt].sum=T[rs].sum,T[rt].ct=T[rs].ct;
}
}
void update(int &rt,int l,int r,int pos,int val){
if(!rt) rt=++tot;
if(l==r){
T[rt].ct+=val;T[rt].sum=l;
return;
}
int mid = l+r>>1;
if(pos<=mid) update(ls,l,mid,pos,val);
else update(rs,mid+1,r,pos,val);
pushup(rt);
}
int merge(int x,int y,int l,int r){
if(!x||!y) return x+y;
if(l==r){
T[x].ct+=T[y].ct;
T[x].sum=l;
return x;
}
int mid = l+r>>1;
T[x].l=merge(T[x].l,T[y].l,l,mid);
T[x].r=merge(T[x].r,T[y].r,mid+1,r);
pushup(x);
return x;
}
void dfs(int u,int f){
for(int i = h[u]; i; i = nex[i]){
if(to[i]!=f){
dfs(to[i],u);
rt[u]=merge(rt[u],rt[to[i]],1,1e5);
}
}
ans[u]=T[rt[u]].sum;
}
int main(){
int n;
scanf("%d",&n);
for(int i = 1; i <= n; i++){
int c;
scanf("%d",&c);
update(rt[i],1,1e5,c,1);
}
for(int i = 2; i <= n; i++){
int x,y;
scanf("%d%d",&x,&y);
add_edge(x,y);
add_edge(y,x);
}
dfs(1,0);
for(int i = 1; i <= n; i++)
printf("%lld ",ans[i]);
puts("");
return 0;
}