• 树的启发式合并


    树的启发式合并可以解决很多不涉及修改的子树查询问题。

    每次向上合并时,轻链并入重链,可以使得总复杂度由(O(n^2))变成(O(nlog(n)))。因为每次加入重链,子树大小都会翻倍。

    例题:codeforces 600E

    给定一棵树,每个节点都有一个颜色值。
    定义一种颜色值占领一棵子树,当且仅当这种颜色是这棵子树中出现最多的颜色。

    问每个节点为根的子树中,占领这棵子树的颜色值之和。

    代码

    #include <bits/stdc++.h>
    
    #define FOPI freopen("in.txt", "r", stdin)
    #define FOPO freopen("out.txt", "w", stdout)
    
    using namespace std;
    typedef long long LL;
    typedef pair<int, int> pr;
    const int maxn = 1e5 + 100;
    
    int n;
    vector<int> v[maxn];
    map<int, int> col[maxn];
    LL ans[maxn];
    int maxt[maxn];
    
    void merge(int x, int y)
    {
        if (col[x].size() < col[y].size()) {
            swap(col[x], col[y]);
            ans[x] = ans[y];
            maxt[x] = maxt[y];
        }
    
        for (auto val : col[y]) {
            int a = val.first, b = val.second;
            col[x][a] += b;
    
            if (col[x][a] > maxt[x]) {
                maxt[x] = col[x][a];
                ans[x] = a;
            }
            else if (col[x][a] == maxt[x]) {
                ans[x] += a;
            }
        }
        col[y].clear();
    }
    
    void dfs(int x, int from)
    {
        for (int y : v[x]) {
            if (y == from) continue;
            dfs(y, x);
            merge(x, y);
        }
    }
    
    int main()
    {
        //FOPI;
    
        scanf("%d", &n);
        int x, y;
        for (int i = 1; i <= n; i++) {
            scanf("%d", &x);
            col[i][x] = 1;
            ans[i] = x;
            maxt[i] = 1;
        }
    
        for (int i = 1; i <= n-1; i++) {
            scanf("%d%d", &x, &y);
            v[x].push_back(y), v[y].push_back(x);
        }
    
        dfs(1, 0);
    
        printf("%lld", ans[1]);
        for (int i = 2; i <= n; i++)
            printf(" %lld", ans[i]);
        puts("");
    }
    
    
  • 相关阅读:
    10 查看创建表的语句:show create table emp;
    9 常用命令?
    8 如何查看表中的数据?
    7 查看表结构
    构建之法阅读笔记3
    每日汇报
    每周总结
    每日汇报
    每周总结
    每日总结
  • 原文地址:https://www.cnblogs.com/ruthank/p/10910428.html
Copyright © 2020-2023  润新知