Educational Codeforces Round 2E:http://codeforces.com/contest/600/problem/E
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
大致思路:从叶子节点向上更新控制颜色即可,但是必须用map映射而且要将小树合并到大树当中,否则会MLE
#include <cstdio> #include <cstring> #include <vector> #include <map> #include <algorithm> using namespace std; int n,c[100005],index[100005],mx[100005];//c[i]表示i节点的颜色,index[i]表示i节点所对应的cnt下标,mx[index[i]]表示i节点相同颜色出现最多的次数 long long ans[100005],tmp[100005];//tmp[index[i]]表示i节点当前控制颜色总和 map<int,int> cnt[100005];//cnt[index[i]]表示i节点cnt[index[i]].first出现的次数为cnt[index[i]].second vector<int> v[100005]; void Merge(int s,int e) { if(cnt[index[s]].size()<cnt[index[e]].size())//总是将小树合并到大树上,以防MLE swap(index[s],index[e]); for(map<int,int>::iterator it=cnt[index[e]].begin();it!=cnt[index[e]].end();++it) {//枚举小树的map cnt[index[s]][it->first]+=it->second;//i节点中颜色it->first出现次数加it-second if(cnt[index[s]][it->first]>mx[index[s]]) {//如果当前颜色it->first出现次数已大于控制颜色出现次数 mx[index[s]]=cnt[index[s]][it->first];//更新控制线色出现次数 tmp[index[s]]=it->first;//重置控制颜色 } else if(cnt[index[s]][it->first]==mx[index[s]])//如果当前颜色it->first出现次数等于控制颜色出现次数 tmp[index[s]]+=it->first;//控制颜色加上当前颜色 } } void dfs(int pre,int u) { for(int i=0;i<v[u].size();++i) if(v[u][i]!=pre) { dfs(u,v[u][i]); Merge(u,v[u][i]); } ans[u]=tmp[index[u]]; } int main() { int s,e,i; while(1==scanf("%d",&n)) { for(i=1;i<=n;++i) { scanf("%d",c+i); index[i]=i; mx[i]=cnt[i][c[i]]=1; tmp[i]=c[i]; } for(i=1;i<n;++i) { scanf("%d%d",&s,&e); v[s].push_back(e); v[e].push_back(s); } dfs(1,1); for(i=1;i<n;++i) printf("%I64d ",ans[i]); printf("%I64d\n",ans[n]); } return 0; }