组昂树用于统计每个节点的子树的信息。复杂度为\(O(n\log n)\)。
先将原树轻重路径剖分,之后遍历树。solve(u)表示统计u结点子树的答案,考虑以下过程:先调用solve(轻儿子),且不保留计算结果。然后调用solve(重儿子),保留计算结果。最后再计算所有轻儿子的子树的答案和自己的答案,更新答案。最后考虑是否保留计算结果。
calc(u, type) {
contribute f[u] <- type;
for v = each son of u
if mark[v] = False
calc(v, type);
}
solve(u, keep) {
hson = find the heaviest son of u;
for v = each son of u
if v != hson
solve(v, False);
if hson exists {
solve(hson, True);
mark[hson] = True;
}
calc(u, 1);
if hson exists
mark[hson] = False;
if keep = False
calc(u, -1);
}