Educational Codeforces Round 2 E. Lomsat gelral 启发式合并map
2015-11-29 21:30
399 查看
E. Lomsat gelral
Time Limit: 20 SecMemory Limit: 256 MB
题目连接
http://codeforces.com/contest/600/problem/EDescription
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 ≤ 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.
Output
Print n integers — the sums of dominating colours for each vertex.
Sample Input
4 1 2 3 4 1 2 2 3 2 4
Sample Output
10 9 3 4
HINT
题意给你一棵树,告诉你每个节点的颜色,然后让你输出对于这个节点的子树中,出现次数最多的颜色的权值和是多少
题解:
启发式合并map
对于每一个子树,我们都维护一个map,然后从小的合并到大的中
均摊下来复杂度不会很高(雾
代码:
#include<iostream> #include<stdio.h> #include<vector> #include<map> using namespace std; #define maxn 800005 map<int,int> H[maxn]; map<int,int>::iterator it; long long ans[maxn]; vector<int> E[maxn]; int c[maxn]; int id[maxn]; long long M[maxn]; long long M1[maxn]; void uni(int &x,int y) { if(H[x].size()<H[y].size())swap(x,y); for(it = H[y].begin();it!=H[y].end();it++) { H[x][it->first]+=it->second; if(M1[x]==H[x][it->first]) M[x]+=it->first; if(M1[x]<H[x][it->first]) { M1[x]=H[x][it->first]; M[x]=it->first; } } } void solve(int x,int fa) { H[x][c[x]]=1; M1[x]=1,M[x]=c[x]; for(int i=0;i<E[x].size();i++) { if(E[x][i]==fa)continue; solve(E[x][i],x); uni(id[x],id[E[x][i]]); } ans[x]=M[id[x]]; } long long flag = 0; int main() { int n;scanf("%d",&n); for(int i=1;i<=n;i++) { id[i]=i; scanf("%d",&c[i]); } for(int i=1;i<n;i++) { int x,y;scanf("%d%d",&x,&y); E[x].push_back(y); E[y].push_back(x); } solve(1,-1); for(int i=1;i<=n;i++) printf("%lld ",ans[i]); printf("\n"); return 0; }
相关文章推荐
- C语言中常用的string.h的字符函数
- <构建之法>阅读感想
- Mac Jenkins 权限问题
- 《apue》读书笔记 第四章 文件和目录(2)
- Struts2+Spring+Hibernate整合过程详解
- ExpandableListAdapter
- 苹果帝国:正在夹缝中捡金子
- C++关于符号&的各种含义:
- 数据结构基础7.1:简单排序(冒泡、选择、插入)
- MarkDown 图片大小问题
- AllJoyn数据传输过程
- MarkDown 图片大小问题
- 各大网站CSS代码初始化集合
- BZOJ3879: SvT
- [OpenCV] GpuMat and Mat, compare cvtColor perforemence
- gosn解析集合
- [OpenCV] GpuMat and Mat, compare cvtColor perforemence
- 4.0 苹果系统安装之黑苹果(4)
- 4.0 苹果系统安装之黑苹果(4)
- 二维数组中的查找