zoukankan      html  css  js  c++  java
  • CF600E Lomsat gelral 题解 树上启发式合并

    题目链接:https://codeforces.com/problemset/problem/600/E

    题目大意:求一个以 (1) 为根节点的有根树中每个节点对应的子树中出现次数最多的所有颜色的编号之和。

    解题思路:

    树上启发式合并。

    额外的处理(如何在 (O(1)) 时间内求出节点 (u) 当前对应的出现次数最多的节点编号之和):

    • (res[u]) 表示 (u) 对应的答案
    • (ap[i]) 表示目前出现次数等于 (i) 的颜色编号和
    • (apid) 表示目前出现次数最多的颜色的出现次数

    示例代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 100010;
    int n, m, sz[maxn], c[maxn], cnt[maxn];
    bool big[maxn];
    vector<int> g[maxn];
    
    void getsz(int u, int p) {
        sz[u] ++;
        for (auto v: g[u])
            if (v != p)
                getsz(v, u), sz[u] += sz[v];
    }
    
    long long res[maxn], ap[maxn];
    int apid;
    
    void add(int u, int p, int x) {
    
        int cc = cnt[ c[u] ];
        ap[cc] -= c[u];
        ap[cc+x] += c[u];
        if (x > 0 && apid < cc+x) apid = cc+x;
        if (x < 0 && cc == apid && ap[cc] == 0) apid --;
    
        cnt[ c[u] ] += x;
        for (auto v: g[u])
            if (v != p && !big[v])
                add(v, u, x);
    }
    void dfs(int u, int p, bool keep) {
        int mx = -1, bigSon = -1;   // mx表示重儿子的sz, bigSon表示重儿子编号
        for (auto v: g[u])
            if (v != p && sz[v] > mx)
                mx = sz[ bigSon = v ];
        for (auto v: g[u])
            if (v != p && v != bigSon)
                dfs(v, u, false);
    
        if (bigSon != -1)
            dfs(bigSon, u, true),
            big[bigSon] = true;
        add(u, p, 1);
        assert(apid > 0);
        res[u] = ap[apid];
        if (bigSon != -1)
            big[bigSon] = 0;
        if (!keep)
            add(u, p, -1);
    }
    int main() {
        cin >> n;
        for (int i = 1; i <= n; i ++) cin >> c[i];
        for (int i = 1; i < n; i ++) {
            int a, b;
            cin >> a >> b;
            g[a].push_back(b);
            g[b].push_back(a);
        }
        getsz(1, -1);
        dfs(1, -1, false);
        for (int i = 1; i <= n; i ++) cout << res[i] << " ";
        return 0;
    }
    
  • 相关阅读:
    [tarjan][树上差分] Codeforces 555E Case of Computer Network
    [线段树] Jzoj P1214 项链工厂
    [矩阵乘法] Jzoj P2288 沼泽鳄鱼
    [状压dp][dfs] Jzoj P2679 跨时代
    [spfa][差分约束] Bzoj 2330 糖果
    [spfa] Bzoj 2118 墨墨的等式
    [倍增][Floyd] Bzoj 2165 大楼
    [虚树][树形dp] Bzoj P3611 大工程
    [虚树][树形dp] Bzoj P2286 消耗战
    [数位dp] Jzoj P3316 非回文数字
  • 原文地址:https://www.cnblogs.com/quanjun/p/13927713.html
Copyright © 2011-2022 走看看