浅析树链剖分Orz

本文思路参考自何开大佬

引子

相信各位大佬一定会线段树这种非常实用的数据结构

那么如果我们要维护一棵树上的链的权值的时候怎么办

就比如说BZOJ1036树的统计这道题目

可能诸位草率地想想线段树是可以口头AC的,But 这是在一棵树上,线段树支持的连续的区间操作

在这棵树上,如果链的编号断断续续,那么我们的线段树就和暴力没有什么区别有一点点区别了

概念

所以这里就需要用到树链剖分,这种可以支持树上链操作的数据结构

树链剖分有很多高大上的名词需要我们去记

我们先定义一些概念东东

size[u]表示以u为根的树的大小

dep[u]表示u的深度(根的深度定为1)

fa[u]表示u的爸爸(???)

有了这些东东,我们开始定义真正的概念

重儿子:u的所有儿子v中,size[v]最大的v称为u的重儿子

轻儿子:u的所有儿子v中,不是重儿子的都被叫做轻儿子

重边:u 连向它的重儿子的边称为重边

轻边:u连向它的轻儿子的边称为轻边

重链:组成这条链的所有的边都是重边

轻链:组成这条连的所有边都是轻边

一些小性质

性质1:V为u的轻儿子,则必有size[V] <= size[u] / 2

这个性质证明可以用到反证法

如果存在V为轻儿子并且size[V] > size[u] / 2

我们会发现如果一个节点成为重儿子的条件就是size[V] >= size[u] / (SonNumber[u])      //SonNumber[u]表示u的儿子的数目

因为size[u] / 2 > size[u] / 3 > size[u] / 4 ………………………………

而且size[V] 是不可能大于size[u]的

所以,V为这时候只能为重儿子

与假设不符

证毕~~~~

性质2:从根到某一节点的路径上,轻边的数量不超过O(log N),重链的数目不超过O(log N)

这个我们也是可以证明的

因为我们可以从性质1直接推得轻边的数量不超过O(log N)

后来我们发现

没存在一条轻边,就会出现两条重链

所以重链的数量不超过O(log N)

证毕~~~~

操作

 核心操作其实有两个

其中一个是找出所有的重儿子,因为重儿子找出来以后,重边也就找出来了

第二个操作就是找出所有的重链

那么来考虑修改和查询操作

 如果是修改的话,我们线段树凉拌加个蛋

如果是查询的话,我们改一点点点点还是凉拌加个蛋

我们如果可以将两个节点移到同一个重链上

然后再进行线段树上的操作就行了

对于在将一个节点移到同一个重链时,代码非常的好理解

但是代码中有一个地方打错了

 

 

 

 

posted @ 2017-09-04 20:55  雒煜翾  阅读(148)  评论(0编辑  收藏  举报