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); } }