dsu on tree
这么简单的东西我现在才学,血亏...
on tree大家都能翻译过来。至于dsu,大概就是并查集的意思吧。
但是这并不代表并查集上树了,只是代表用到了启发式合并的思想。
进入正题:
我们有一颗树,有对于子树的询问。这种题暴力就是遍历每个节点的子树中的所有信息暴力统计出来更新答案,然后消除该节点的贡献。
暴力是$n^2$的显然,但如果我们仅仅把遍历每个节点的顺序变一下,复杂度就能降到$nlogn$。
这是怎么做到的呢?首先有一个性质:对于某个节点u,它所有儿子的信息都可以保留。
但是我们在dfs时永远都是先遍历u的所有子节点v,然后才遍历u,在遍历其中一个节点$v_i$的时候必须要其他的v的信息清除。
根据上面的性质,我们知道,像树剖那样求出每个节点的重儿子,对于节点u,最后遍历重儿子,并保留重儿子的信息。这样我们就不用清除重儿子的信息了。
感觉复杂度没降多少啊,怎么就$nlogn$了呢?
细分析,会发现一个节点到根的路径上轻边个数不会超过$logn$。这是因为如果轻边个数大于了$logn$,那么势必重边遍历的节点大于2^(logn),也就是大于n,与只有n个节点不符。
再观察:一个点被访问到,只有两种情况
1、在暴力统计轻边的时候访问到。根据前面的性质,该次数小于$logn$
2、通过重边在遍历的时候被访问到,显然只有一次
由此得到dsu的步骤:
1.遍历每一个节点
2.递归解决所有的轻儿子,同时消除递归产生的影响
3.递归重儿子,不消除递归的影响
4.统计所有轻儿子对答案的影响
5.更新该节点的答案
6.删除所有轻儿子对答案的影响
如果计算贡献是$O(1)$,那么总复杂度便是$O(nlogn)$。
由此可见,dsu可以解决一些不带修改的子树询问问题。
众人皆醉我独醒,举世皆浊我独清