首页 > 学院 > 开发设计 > 正文

codeforces 600 E. Lomsat gelral (dsu on the tree)

2019-11-06 06:54:36
字体:
来源:转载
供稿:网友

E. Lomsat gelraltime limit per test2 secondsmemory limit per test256 megabytesinputstandard inputoutputstandard output

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.

Examplesinput
41 2 3 41 22 32 4output
10 9 3 4input
151 2 3 1 2 3 3 1 1 3 2 2 1 2 31 21 31 41 141 152 52 62 73 83 93 104 114 124 13output
6 5 4 3 2 3 3 1 1 3 2 2 1 2 3

题目大意:求每个点的子树中颜色的出现数量最多的颜色的和。

题解:dsu on the tree

树上启发式合并。其实是一个很暴力的做法,用来解决统计树上一个节点的子树中具有某种特征的节点数,或者子树中的某个值。

做法非常的暴力,就是如果是轻儿子,每次统计完了就将影响消除,如果是重儿子就保留。每次统计答案的时候,先计算轻儿子,在计算中儿子。

最后均摊的时间复杂度是O(nlogn),时间复杂度的证明我也不太会,想明白了再来写。。。。。

#include<iostream>#include<cstdio>#include<algorithm>#include<cmath>#include<cstring>#define N 200003#define LL long long using namespace std;int n,m,point[N],v[N],nxt[N],mark[N];int size[N],son[N],tot;LL cx,sum,num[N],ans[N],col[N];void add(int x,int y){	tot++; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;	tot++; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;}void solve(int x,int f){	size[x]=1;	for (int i=point[x];i;i=nxt[i]) {		if (v[i]==f) continue;	    solve(v[i],x);		size[x]+=size[v[i]];		if (size[v[i]]>size[son[x]]) son[x]=v[i];	}}void calc(int x,int f,int val){	num[col[x]]+=(LL)val;	if (val>0&&num[col[x]]>=cx) {	 if (num[col[x]]>cx) sum=0,cx=num[col[x]];	 sum+=(LL)col[x];	}	for (int i=point[x];i;i=nxt[i])	 if (v[i]!=f&&!mark[v[i]]) calc(v[i],x,val);}void dfs(int x,int f,bool k=0){	for (int i=point[x];i;i=nxt[i])	 if (v[i]!=f&&v[i]!=son[x]) dfs(v[i],x,0);	if (son[x]) dfs(son[x],x,1),mark[son[x]]=1;	calc(x,f,1);	ans[x]=sum;	if (son[x]) mark[son[x]]=0;	if (!k) calc(x,f,-1),cx=sum=0;}int main(){	freopen("a.in","r",stdin);	freopen("my.out","w",stdout);	scanf("%d",&n);	for (int i=1;i<=n;i++) scanf("%I64d",&col[i]);	for (int i=1;i<n;i++) {		int x,y; scanf("%d%d",&x,&y);		add(x,y);	}	solve(1,0);	dfs(1,0,0);	for (int i=1;i<=n;i++) printf("%I64d ",ans[i]);	printf("/n");} 


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表