dsu on tree模板

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

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

题目:CF600E

#include<bits/stdc++.h>
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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值