DSU ON TREE

DSU ON TREE,在处理一些可以离线的有关于子树的询问问题时,使用其可以将复杂度从 \(O(nm)\) 降至 \(O(n\log n)\),是一种非常实用的方法。

它的思想大概是,先尽量往轻儿子跳,统计。如果是轻儿子则遍历完子树后消除影响,若是重儿子则保留。然后暴力统计轻儿子。

看起来很抽象,我们结合下图模拟一下就很容易懂了(我们只探究点2及其子树):

遍历过程如下:
我们设 dfs 当前遍历到的点为 \(x\)

x:1->2->5,因为 5 的儿子遍历完了,所以统计 5 的答案,此时 ans={5},为子树 5 的答案
x:5->2,消除 5 及子树的影响,此时 ans={}
x:2->6->12,因为 12 的儿子遍历完了,所以统计 12 的答案,此时 ans={12},为子树 12 的答案
x:12->6,消除 12 及子树的影响,此时 ans={}
x:6->11,统计 11 的答案,此时 ans={11},为子树 11 的答案
x:11->6,因为 6 的儿子遍历完了,所以统计 6 的答案,因为 11 为重儿子,所以保留,此时 ans={6,11},暴力统计轻儿子 12 及其子树,此时 ans={6,11,12},为子树 6 的答案
x:6->2,因为 2 的儿子遍历完了,所以统计 2 的答案,因为 6 为重儿子,所以保留,此时 ans={2,6,11,12},暴力统计轻儿子 5 及其子树,此时 ans={2,5,6,11,12},为子树 2 的答案
...

为什么是 \(O(n \log n)\)
考虑任意一个节点 \(v\),它会被"暴力插入/删除"几次。
只有当 \(v\) 处于某个祖先的轻儿子子树中时,它才会在那个祖先的"重新加入轻儿子"步骤被遍历。
每次 \(v\) 沿着轻边向上走,所在子树的大小至少翻倍。所以,从 \(v\) 到根的路径上,最多有 \(O(\log n)\) 条轻边。因此,
\(v\) 最多被暴力处理 \(O(\log n)\) 次。
\(n\) 个节点总复杂度就是 \(O(n \log n)\)

posted @ 2026-07-19 16:39  MistyPost  阅读(3)  评论(0)    收藏  举报