• dsu on tree模板


    处理树上不带修改的离线子树问题

    关键词:静态、离线、子树

    题目:CF600E

    #include
    using namespace std;
    typedef long long ll;
    const int N = 1e5 + 20, M = 2e5 + 20;
    int n, c[N], cnt[N];
    int flag, maxc;
    ll ans[N], sum;

    int e[M], ne[M], h[M], idx;
    void add(int u, int v){
        e[idx] = v, ne[idx] = h[u], h[u] = idx++;
    }

    // 找重儿子
    int siz[N], son[N];
    void dfs(int u, int f){
        siz[u] = 1;
        for(int i = h[u]; ~i; i = ne[i]){
            int v = e[i];
            if(v == f) continue;
            dfs(v, u);
            siz[u] += siz[v];
            if(siz[v] > siz[son[u]]){
                son[u] = v;
            }
        }
    }

    // 统计答案
    void count(int u, int f, int val){
        cnt[c[u]] += val;
        if(cnt[c[u]] > maxc){
            maxc = cnt[c[u]];
            sum = c[u];
        }
        else if(cnt[c[u]] == maxc)
            sum += c[u];
        for(int i = h[u]; ~i; i = ne[i]){
            int v = e[i];
            if(v == f || v == flag) continue;
            count(v, u, val);
        }
    }

    // dsu on tree 模板
    void dfs_dsuontree(int u, int f, bool keep){
        // 计算轻儿子及其子树 统计答案并删除贡献
        for(int i = h[u]; ~i; i = ne[i]){
            int v = e[i];
            if(v == f || v == son[u]) continue;
            dfs_dsuontree(v, u, false);
        }
        // 计算重儿子及其子树 统计答案不删贡献
        if(son[u]){
            dfs_dsuontree(son[u], u, true);
            flag = son[u];
        }
        // 暴力统计u及其所有轻儿子的贡献 合并到刚算出的重儿子信息里
        count(u, f, 1);
        flag = 0;
        ans[u] = sum;
        // 把需要删除贡献删除
        if(!keep){
            count(u, f, -1);
            sum = maxc = 0;
        }
    }

    int main(){
        memset(h, -1, sizeof h);
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) scanf("%d", &c[i]);
        for(int i = 1; i < n; i++){
            int u, v;
            scanf("%d%d", &u, &v);
            add(u, v);
            add(v, u);
        }
        dfs(1, -1);
        dfs_dsuontree(1, 0, false);
        for(int i = 1; i <= n; i++){
            printf("%lld ", ans[i]);
        }
        return 0;
    }

  • 相关阅读:
    Xmake v2.7.1 发布,更好的 C++ Modules 支持
    北京某中厂凉经
    Uniapp 动态修改状态栏、导航栏背景色、字体颜色插件 Ba-AppBar
    flex&bison系列第三章:写一个简单的计算器Calculator
    无线通信测量仪器-4945B/C 无线电通信综合测试仪
    注解、AOP
    Git使用
    自动化办公更简单了:新版python-office,有哪些更新?
    Dynamsoft Label Recognizer SDK FOR .NET/C++/JAVA
    [Spring MVC7] 解决Redis乱码前缀问题
  • 原文地址:https://blog.csdn.net/Galaxy_Su/article/details/127676083