【Codeforces-600E】Lomsat gelral(dsu on tree)

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   ≤   1 0 5 n (1 ≤ n ≤ 10^5 n(1n105 $) — the number of vertices in the tree.

The second line contains n integers c i ( 1 &lt; = c i &lt; = n ) c_i(1&lt;=c_i&lt;=n) 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 4
output
10 9 3 4

input
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
output
6 5 4 3 2 3 3 1 1 3 2 2 1 2 3

这题比较牛逼,我第一次接触这种类型的题,其实算是一种启发式合并的问题,dsu on tree可以解决一类静态树上的问题。
代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<set>
#define ll long long
#define maxx 100005
#define INF 0x7f7f7f7f
using namespace std;
int n;
int head[maxx],to[maxx<<1],_next[maxx<<1];
int edge;
inline void addEdge(int x,int y)
{
    to[++edge]=y,_next[edge]=head[x],head[x]=edge;
    to[++edge]=x,_next[edge]=head[y],head[y]=edge;
}
//����
int _size[maxx];
int son[maxx];
void dfs1(int u,int fa)
{
    _size[u]=1;
    int maxson=-1;
    for(int i=head[u];i;i=_next[i])
    {
        int v=to[i];
        if(v==fa)continue;
        dfs1(v,u);
        _size[u]+=_size[v];
        if(_size[v]>maxson)
        {
            son[u]=v;
            maxson=_size[v];
        }
    }
}
int l[maxx],r[maxx],_index;
int a[maxx],b[maxx];
void dfs2(int u,int fa)
{
    l[u]=++_index;
    a[_index]=b[u];
    for(int i=head[u];i;i=_next[i])
    {
        int v=to[i];
        if(v==fa)continue;
        dfs2(v,u);
    }
    r[u]=_index;
}
int cnt[maxx];
ll res=0;
int _max=0;
void del(int u)
{
    res=0;
    _max=0;
    for(int i=l[u];i<=r[u];i++)
        cnt[a[i]]=0;
}
void add(int u)
{
    for(int i=l[u];i<=r[u];i++)
    {
        cnt[a[i]]++;
        if(cnt[a[i]]>_max)
        {
            res=a[i];
            _max=cnt[a[i]];
        }
        else if(cnt[a[i]]==_max)res+=a[i];
    }
}
ll ans[maxx];
void dfs(int u,int fa)
{
    for(int i=head[u];i;i=_next[i])
    {
        int v=to[i];
        if(v==fa)continue;
        if(son[u]!=v)
        {
            dfs(v,u);
            del(v);
        }
    }
    if(son[u])dfs(son[u],u);
    for(int i=head[u];i;i=_next[i])
    {
        int v=to[i];
        if(v==fa)continue;
        if(son[u]!=v)add(v);
    }
    cnt[b[u]]++;
    if(cnt[b[u]]>_max)
    {
        res=b[u];
        _max=cnt[b[u]];
    }
    else if(cnt[b[u]]==_max)res+=b[u];
    ans[u]=res;
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)scanf("%d",b+i);
    int x,y;
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&x,&y);
        addEdge(x,y);
    }
    dfs1(1,0);
    dfs2(1,0);
    dfs(1,0);
    for(int i=1;i<n;i++)
        printf("%I64d ",ans[i]);
    printf("%I64d\n",ans[n]);
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值