• CF 600 E. Lomsat gelral


    E. Lomsat gelral

    http://codeforces.com/contest/600/problem/E

    题意:

      求每个子树内出现次数最多的颜色(如果最多的颜色出现次数相同,将颜色编号求和)。

    分析:

      dsu on tree。

      这个可以解决一系列不带修改的子树查询问题。

      考虑暴力的思路:就是枚举每个子树,计算每个颜色出现的个数。统计答案。

      dsu on tree:最后一个子树枚举计算完了,它的贡献可以保留,然后用其它的子树去合并。(最后一棵子树是最大的)。现在的复杂度就是nlogn了。

    代码:

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<iostream>
     6 #include<cctype>
     7 #include<set>
     8 #include<vector>
     9 #include<queue>
    10 #include<map>
    11 using namespace std;
    12 typedef long long LL;
    13 
    14 inline int read() {
    15     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
    16     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    17 }
    18 
    19 const int N = 100005;
    20 
    21 int head[N], nxt[N << 1], to[N << 1], En;
    22 int fa[N], siz[N], son[N], cnt[N], col[N], Mx;
    23 LL ans[N], Sum;
    24 
    25 void add_edge(int u,int v) {
    26     ++En; to[En] = v; nxt[En] = head[u]; head[u] = En;
    27     ++En; to[En] = u; nxt[En] = head[v]; head[v] = En;
    28 }
    29 
    30 void dfs(int u) {
    31     siz[u] = 1;
    32     for (int i=head[u]; i; i=nxt[i]) {
    33         int v = to[i];
    34         if (v == fa[u]) continue;
    35         fa[v] = u;
    36         dfs(v);
    37         siz[u] += siz[v];
    38         if (!son[u] || siz[son[u]] < siz[v]) son[u] = v;
    39     }
    40 }
    41 
    42 void add(int u) {
    43     cnt[col[u]] ++;
    44     if (cnt[col[u]] > Mx) Mx = cnt[col[u]], Sum = col[u];
    45     else if (cnt[col[u]] == Mx) Sum += col[u];
    46 }
    47 void Calc(int u) {
    48     add(u);
    49     for (int i=head[u]; i; i=nxt[i]) 
    50         if (to[i] != fa[u]) Calc(to[i]);
    51 }
    52 void Clear(int u) {
    53     cnt[col[u]] --;
    54     for (int i=head[u]; i; i=nxt[i]) 
    55         if (to[i] != fa[u]) Clear(to[i]);
    56 }
    57 
    58 void solve(int u,bool c) {
    59     for (int i=head[u]; i; i=nxt[i]) 
    60         if (to[i] != fa[u] && to[i] != son[u]) solve(to[i], 0);
    61     if (son[u]) solve(son[u], 1);
    62     add(u);
    63     for (int i=head[u]; i; i=nxt[i]) 
    64         if (to[i] != fa[u] && to[i] != son[u]) Calc(to[i]);
    65     ans[u] = Sum;
    66     if (!c) Clear(u), Mx = 0, Sum = 0;
    67 }
    68 
    69 int main() {
    70     int n = read();
    71     for (int i=1; i<=n; ++i) col[i] = read();
    72     for (int i=1; i<n; ++i) {
    73         int u = read(), v = read(); 
    74         add_edge(u, v);
    75     }
    76     dfs(1);
    77     solve(1, 1);
    78     for (int i=1; i<=n; ++i) printf("%I64d ",ans[i]);
    79     return 0;
    80 }
  • 相关阅读:
    篮球中PRA意思
    篮球中PRA意思
    Ajax介绍
    QQ播放器代码
    QQ播放器代码
    QQ播放器代码
    DataSet对象
    DataReader对象
    Connection对象
    DataAdapter对象
  • 原文地址:https://www.cnblogs.com/mjtcn/p/9711168.html
Copyright © 2020-2023  润新知