dsu on tree

纯暴力时间与空间都需要n^2 但是有多余的删除操作 可以利用树链剖分的思想优化

思路如下:

对于每个节点
1.dfs函数统计所有轻儿子的答案
2.dfs函数统计重儿子的答案 同时用另一个函数遍历除重儿子那颗子树之外的所有子树 得到当前节点的答案
3.如果当前节点是轻儿子的话 消除对目标数组的影响 是重儿子则不用

Edg
int n, cc[SZ], col[SZ], ks[SZ], anss[SZ];
int sz[SZ], son[SZ];
void gs(int x, int f = 0) {
        sz[x] = 1;
        for esb(x, e, b) {
                if (b == f) {
                        continue;
                }
                gs(b, x);
                sz[x] += sz[b];
                if (sz[b] > sz[son[x]]) {
                        son[x] = b;
                }
        }
}
int skip = 0;
void edt(int x, int f, int v) {
        cc[col[x]] += v;
        for esb(x, e, b)
                if (b != f && b != skip) {
                        edt(b, x, v);
                }
}
void dfs(int x, int f = 0, bool kep = 0) {
        for esb(x, e, b)
                if (b != f && b != son[x]) {
                        dfs(b, x);
                }
        if (son[x]) {
                dfs(son[x], x, 1), skip = son[x];
        }
        edt(x, f, 1);
        anss[x] = cc[ks[x]];
        skip = 0;
        if (!kep) {
                edt(x, f, -1);
        }
}
原文地址:https://www.cnblogs.com/Aragaki/p/10572960.html