Codeforces 600.E Lomsat gelral

E. Lomsat gelral
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard 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.

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裸题.
   先把每个点的重儿子处理出来.然后从根开始dfs处理.先dfs轻儿子,递归回来时会把贡献给清除掉,然后dfs重儿子,重儿子的贡献不会被清除. 接着计算轻儿子子树的贡献,如果当前子树是父亲的轻子树,则删除当前子树的贡献.
为什么要先dfs轻儿子?因为想要保证当前记录的答案只有当前子树的答案,不包含其他子树的答案.每次dfs轻儿子后都会清除贡献,而dfs重儿子不会.所以先dfs重儿子可能会计算其它子树的答案.
   每个节点会被计算O(log n)次,总复杂度O(nlogn).
   这个算法是有局限性的,它是用来解决无修改统计子树答案的题,也就是说题目必须满足:1.没有修改 2.只查询子树的答案.
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long ll;

const ll maxn = 100010;

ll n,a[maxn],ans[maxn],head[maxn],to[maxn * 2],nextt[maxn * 2],tot = 1,son[maxn],sizee[maxn],num[maxn],maxx,vis[maxn];

struct node
{
    ll x,v;
} e[maxn];

void add(ll x,ll y)
{
    to[tot] = y;
    nextt[tot] = head[x];
    head[x] = tot++;
}

void dfs1(ll u,ll fa)
{
    sizee[u] = 1;
    for (ll i = head[u]; i; i = nextt[i])
    {
        ll v = to[i];
        if (v == fa)
            continue;
        dfs1(v,u);
        sizee[u] += sizee[v];
        if (sizee[v] > sizee[son[u]])
            son[u] = v;
    }
}

void update(ll u,ll fa,ll v)
{
    ll &c = num[a[u]];
    e[c].x--;
    e[c].v -= a[u];
    c += v;
    e[c].x++;
    e[c].v += a[u];
    if (v == 1)
        maxx = max(maxx,c);
    else
        if (!e[maxx].x)
            maxx--;
    for (ll i = head[u]; i; i = nextt[i])
    {
        ll vv = to[i];
        if (vv == fa || vis[vv])
            continue;
        update(vv,u,v);
    }
}

void dfs2(ll u,ll fa,ll flag)
{
    for (ll i = head[u]; i; i = nextt[i])
    {
        ll v = to[i];
        if (v == fa || v == son[u])
            continue;
        dfs2(v,u,0);
    }
    if (son[u])
        dfs2(son[u],u,1),vis[son[u]] = 1;
    update(u,fa,1);
    ans[u] = e[maxx].v;
    vis[son[u]] = 0;
    if (flag == 0)
        update(u,fa,-1);
}

int main()
{
    scanf("%I64d",&n);
    for (ll i = 1; i <= n; i++)
        scanf("%I64d",&a[i]);
    for (ll i = 1; i < n; i++)
    {
        ll x,y;
        scanf("%I64d%I64d",&x,&y);
        add(x,y);
        add(y,x);
    }
    dfs1(1,0);
    dfs2(1,0,1);
    for (ll i = 1; i <= n; i++)
        printf("%I64d ",ans[i]);

    return 0;
}
 
原文地址:https://www.cnblogs.com/zbtrs/p/8450276.html