树链剖分 树剖求lca 学习笔记

树链剖分

顾名思义,就是把一课时分成若干条链,使得它可以用数据结构(例如线段树)来维护

一些定义:

重儿子:子树最大的儿子

轻儿子:除了重儿子以外的儿子

重边:父节点与重儿子组成的边

轻边:除重边以外的边

重链:重边连接而成的链

轻链:轻边连接而成的链

链头:一条链上深度最小的点

 

第一步:进行进行轻重边的划分。

定义size[x]为以x为根的子树节点个数,令v为u儿子中size值最大的节点,那么(u,v)就是重边,其它出边都是轻边

两个重要性质:

1.轻边(u,v)中,Size[v]<size[u]/2 显然,如果儿子v的size>=size[u],则它应该是重边,u的子树中没有size比他更大的

2.从根到某一点的路径上,不超过logn条轻边和不超过logn条重路径。这条性质直接保证了树链剖分的复杂度

进行两次dfs,第一次dfs记录下所有的重边,第二次dfs连接重边,形成重链。

具体过程:在每一个节点,先递归重儿子,沿着重边向下拓展,形成一条重链,接着递归其他轻儿子,成为其子树中重链的起点 

定义:

size[]数组:用来保存以x为根的子树节点个数

top[]数组:用来保存当前节点的所在链的顶端节点

son[]数组:用来保存重儿子

dep[]数组:用来保存当前节点的深度

fa[]数组:用来保存当前节点的父亲

dfn[]数组:用来保存树中每个节点剖分后的新编号(按第二遍dfs的访问顺序,先重儿子)

pos[]数组:用来保存当前节点在线段树中的位置

 

第二步 查询lca

我们象倍增求lca一样,每次跳到一条链的链首,然后跳到链首的父节点,重复前面的过程

直到跳到同一条链上,这时,深度较小的节点就是lca

注意前面的两个性质,它们保证的树剖的复杂度只有很小的logn

代码解释:a^b即a!=b

Dp即dep

 

转载于:https://www.cnblogs.com/lzy-blog/p/11320613.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值