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.
Input
The first line contains integer n (1 ≤ n ≤ ) — 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.
Output
Print n integers — the sums of dominating colours for each vertex.
Examples
input
4 1 2 3 4 1 2 2 3 2 4output
10 9 3 4input
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 13output
6 5 4 3 2 3 3 1 1 3 2 2 1 2 3
题意:有一棵n个节点的树,每个节点有一个颜色。求以每个节点为根的子树中出现次数最多的颜色编号之和(出现次数最多的颜色可能有多个)。
思路:用map记录每个子树中颜色出现的个数,用maxn[x]表示以x为根的子树中颜色出现次数的最大值,然后从叶子节点向上进行合并,合并的时候用到启发式合并,即从小集合向大集合中进行合并,这样总合并的时间复杂度为O(nlogn)。假设A集合为大集合,B集合为小集合,则具体合并方法为,将B的map中的每个元素加入到A集合中,如果加入A集合后A的map存储的值大于maxn[A],则更新maxn[A],并且更新A的答案,如果map的值等于maxn[A],显然这个颜色没有被加入答案,把这颜色的编号加入答案。
关于启发式合并时间复杂度方面的计算,可以这样理解:每一次从一个小集合合并到一个较大的集合,则这个集合的大小至少是原来小集合的两倍,这样最坏情况下会合并logn次,所以每个点最多会被合并logn次,总的复杂度就为nlogn。树上的启发式合并通常写法是把一个节点的所有轻儿子合并到重儿子上,而我的写法是直接用儿子节点和父节点两两进行比较,这样虽然可能不是时间最优,但是写法简洁。
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#define LL long long
using namespace std;
unordered_map<int,int> mp[100010];
LL ans[100010];
int maxn[100010];
int a[100010];
vector<int> e[100010];
void dfs(int x,int fa)
{
mp[x][a[x]] = 1;
maxn[x] = 1;
ans[x] = a[x];
for(int i=0;i<e[x].size();i++)
{
int xx = e[x][i];
if(xx == fa)
continue;
dfs(xx,x);
if(mp[x].size() < mp[xx].size())
{
swap(mp[x],mp[xx]);
swap(maxn[x],maxn[xx]);
ans[x] = ans[xx];
}
for(auto it : mp[xx])
{
mp[x][it.first] += it.second;
if(mp[x][it.first] > maxn[x])
{
maxn[x] = mp[x][it.first];
ans[x] = it.first;
}
else if(mp[x][it.first] == maxn[x])
{
ans[x] += it.first;
}
}
}
}
int main(void)
{
int n,i,j;
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
for(i=2;i<=n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
e[x].push_back(y);
e[y].push_back(x);
}
dfs(1,-1);
for(i=1;i<=n;i++)
printf("%lld ",ans[i]);
return 0;
}