\(\text{dsu on tree}\)(树上启发式合并)是用于统计子树信息的算法。
基于CF上Arpa的那套理论
常数小,代码易写,于是学习了一下
前置技能
- 树链剖分-重链剖分
- 重链/轻链的复杂度
思想
\(\text{dsu on tree}\)依赖于轻重链划分
其思想是:只保留重子树的信息给祖先再利用
算法流程
\(\text{dsu on tree}\)的过程可以如下描述:
- 处理轻子树的答案
- 处理重子树的答案,并保留贡献
- 获取轻子树对答案的贡献,得到当前点的答案
- 如果当前点是轻儿子,去除当前点的贡献
伪代码如下:
1 | void change(int x,int w){ |
复杂度分析
这样的做法看似很暴力,其实有理有据
考虑change带来的复杂度:
只有轻儿子才会把子树信息加入父节点
重链剖分把任意根到叶子路径划分成了不超过\(logn\)条轻边和\(logn\)条重链
每个点到根路径都有不超过\(logn\)条轻边
也就是说,每个点被change了\(logn\)次
所以总复杂度是\(O(n+nlogn)\)的