浅谈树链剖分(每日不间断更新中)
浅谈树链剖分 by ksq2013,参考蒋一瑶ppt
- [简介]:树链剖分就是把一棵树(可以是多叉树)转化成多条链,然后用各种数据结构进行维护,复杂度是O(log2 n)❶,树链剖分的问题中树的路径一般赋有边权。
- [剖分依据]:方法大致有两种,其一是随机化剖分,其二是启发式剖分,我学习启发式剖分,以树上路径“轻”、“重”作为估价标准,也就是轻重链剖分。
- [剖分步骤]:1)将树中的边分为轻边和重边。
2)定义size(x)为以x为根的子树的节点个数。
3)找到节点V为节点U的儿子中size最大的节点,那么边(U,V)成为重边。
4)树中除重边之外的边就是轻边。
5)重路径:一条全部由重边构成的路径。
- [剖分性质]:1)轻边(U,V),size(U)/2 >= size(V)(想想就知道,若size(V)比size(U)的一半还大,(U,V)必定是重边)
2)从根到某一点的路径上不超过log2 N条轻边,不超过log2 N条重路径❶。
- [剖分实现]:树链剖分的过程为两次DFS(代码参考hzwer.com):
1)第一次DFS,找重边,并记录之。
2)第二次DFS,找连重边为重链。以根为起点,沿重边向下拓展,拉成重链;不在当前重链上的节点都以该节点为起点向下拉一条重链。
- [维护重链]:剖分完以后,每条重链相当于一段区间,用数据结构维护之:把所有重链首尾相接,放到一数据结构上,维护该整体即可。
- [维护操作]:1)单点更新:单独修改一个点的权值,在数据结构中根据编号直接修改。
2)区间更新:修改点U到V路径上的权值。
I:若U、V在同一重链上,直接用数据结构修改U~V区间的值;
II:A:若fa[top[U]]与V在同一重链上,修改点U与top[U]间各权值,然后U跳至fa[top[U]],直到U与V在同一重链,进入I;
B:若U向上经过若干条重链和轻边与V在同一重链上,不断修改当前U和top[U]间的各权值,再将U跳至fa[top[U]],知道U与V在同一重链,进入I;
C:若U和V都是向上经过若干条重链和轻边,到达同一重链,则每次在U和V中,找deep[top[x]]较大的点x,修改x与top[x]间的各权值,再跳至fa[top[x]],直到U与V在同一重链,进入I;
总的来说,情况A、B是情况C比较特殊的两种;而I也是II的特殊情况。因此这一操作只需一个过程函数即可。
- [维护实现]:
- [询问实现]:
- [具体程序]:见本人博客的树剖专题:http://blog.csdn.net/keshuqi/article/category/6315845