写几个注意点
- push_up操作直接在函数内做,不然不好统计
- 空间复杂度是O(nlogn),所以在合并子树时要尽量节省空间
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
int tnt=0,rt[N];
int n,colr[N],cnt=0,head[N];
struct edge{
int link,v;
}q[N<<1];
ll ans[N];
struct node{
int l,r;
int mx;
ll val;
}tree[N*20];//这里一定要注意
void put(int u,int v){
q[++cnt].v=v;
q[cnt].link=head[u];
head[u]=cnt;
}
void merge(int u,int v,int l,int r){
if(l==r){
tree[u].val=l;
tree[u].mx+=tree[v].mx;
return;
}
int ls=tree[u].l,rs=tree[u].r,lss=tree[v].l,rss=tree[v].r;
int mid=(l+r)>>1;
if(lss){
if(!ls){
ls=lss;
tree[u].l=lss;
}
else merge(ls,lss,l,mid);
}
if(rss){
if(!rs){
rs=rss;
tree[u].r=rss;
}
else merge(rs,rss,mid+1,r);
}
if(tree[ls].mx<tree[rs].mx){
tree[u].val=tree[rs].val;
tree[u].mx=tree[rs].mx;
}
else if(tree[rs].mx<tree[ls].mx){
tree[u].val=tree[ls].val;
tree[u].mx=tree[ls].mx;
}
else {
tree[u].val=tree[ls].val+tree[rs].val;
tree[u].mx=tree[ls].mx;
}
}
void add(int u,int k,int l,int r){
if(l==r){
tree[u].mx++;
tree[u].val=l;
return;
}
int mid=(l+r)>>1,ls=tree[u].l,rs=tree[u].r;
if(k<=mid){
if(!ls){
ls=++tnt;
tree[u].l=ls;
}
add(ls,k,l,mid);
}
else{
if(!rs){
rs=++tnt;
tree[u].r=rs;
}
add(rs,k,mid+1,r);
}
if(tree[ls].mx<tree[rs].mx){
tree[u].val=tree[rs].val;
tree[u].mx=tree[rs].mx;
}
else if(tree[rs].mx<tree[ls].mx){
tree[u].val=tree[ls].val;
tree[u].mx=tree[ls].mx;
}
else {
tree[u].val=tree[ls].val+tree[rs].val;
tree[u].mx=tree[ls].mx;
}
}
void dfs(int s,int fa){
for(int i=head[s];i;i=q[i].link){
int v=q[i].v;
if(v==fa) continue;
dfs(v,s);
merge(rt[s],rt[v],1,n);
}
add(rt[s],colr[s],1,n);
ans[s]=tree[rt[s]].val;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) {
rt[i]=++tnt;
scanf("%d",&colr[i]);
}
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
put(u,v),put(v,u);
}
dfs(1,0);
for(int i=1;i<=n;i++){
printf("%lld ",ans[i]);
}
}