题解: dsu on tree 实质上启发式合并 我们考虑维护节点u的信息 需要将u的儿子的信息和节点信息合并 我们考虑启发式合并 把轻儿子合并到重儿子上 我们考虑n次启发式合并 复杂度nlogn*(合并一次的复杂度) 具体做法那我们考虑树链剖分的时候 划分轻重儿子 保留重儿子信息 清空轻儿子信息 并将轻儿子的信息合并到重儿子上即可
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=3e5+10;
const double eps=1e-8;
#define ll long long
using namespace std;
struct edge{int t;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;}
ll read(){
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
int a[MAXN];
ll ans[MAXN];int cnt[MAXN],cc[MAXN];
int num[MAXN],son[MAXN];
void dfs(int x,int fa){
num[x]=1;
link(x){
if(j->t!=fa){
dfs(j->t,x);
num[x]+=num[j->t];
if(son[x]==-1||num[son[x]]<num[j->t])son[x]=j->t;
}
}
}
void Add(int pos,int key){
cnt[key]++;
if(cnt[key]==cc[pos])ans[pos]+=key;
else if(cnt[key]>cc[pos])ans[pos]=key,cc[pos]=cnt[key];
}
void add(int x,int fa,int pos){
Add(pos,a[x]);
link(x){
if(j->t!=fa)add(j->t,x,pos);
}
}
void clear(int x,int fa){
cnt[a[x]]--;
link(x){
if(j->t!=fa)clear(j->t,x);
}
}
void dfs1(int x,int fa){
link(x){
if(j->t==fa||j->t==son[x])continue;
dfs1(j->t,x);
clear(j->t,x);
}
if(son[x]!=-1)dfs1(son[x],x),cc[x]=cc[son[x]],ans[x]=ans[son[x]];
link(x){
if(j->t==fa||j->t==son[x])continue;
add(j->t,x,x);
}
Add(x,a[x]);
}
int main(){
int n=read();
inc(i,1,n)a[i]=read(),son[i]=-1;
int u,v;
inc(i,1,n-1)u=read(),v=read(),add(u,v),add(v,u);
dfs(1,0);dfs1(1,0);
inc(i,1,n)printf("%lld ",ans[i]);
printf("\n");
}
You are given a rooted tree with root in vertex 1. Each vertex is coloured in some colour.
Let's call colour c dominating in the subtree of vertex v if there are no other colours that appear in the subtree of vertex v more times than colour c. So it's possible that two or more colours will be dominating in the subtree of some vertex.
The subtree of vertex v is the vertex v and all other vertices that contains vertex v in each path to the root.
For each vertex v find the sum of all dominating colours in the subtree of vertex v.
The first line contains integer n (1 ≤ n ≤ 105) — the number of vertices in the tree.
The second line contains n integers ci (1 ≤ ci ≤ n), ci — the colour of the i-th vertex.
Each of the next n - 1 lines contains two integers xj, yj (1 ≤ xj, yj ≤ n) — the edge of the tree. The first vertex is the root of the tree.
Print n integers — the sums of dominating colours for each vertex.
4
1 2 3 4
1 2
2 3
2 4
10 9 3 4
15
1 2 3 1 2 3 3 1 1 3 2 2 1 2 3
1 2
1 3
1 4
1 14
1 15
2 5
2 6
2 7
3 8
3 9
3 10
4 11
4 12
4 13
6 5 4 3 2 3 3 1 1 3 2 2 1 2 3