首页 > 其他分享 >树链剖分

树链剖分

时间:2023-05-23 23:34:36浏览次数:44  
标签:遍历 剖分 复杂度 树链 dfn 子树 重链 边权

我不会做ppt/ll

先来看一棵树:
image

树剖的经典问题:

两种操作,一种是将点 \(u\) 到点 \(v\) 路径上所有点加上一个值;第二种是查询路径 \(u\) 到路径 \(v\) 的点权之和。

显然,普通的树上差分已经无法解决这种问题了。

于是我们需要一种预处理来降低复杂度。

区间修改,这肯定用到线段树,但是这是一棵树,我们如何把他变成连续区间呢。

于是树剖诞生了:我们将整棵树按照重儿子(一个节点的儿子中,以其为根的子树大小是所有儿子中最大的,他就是重儿子)优先遍历,按遍历顺序将每个点打上一个序号(这就是 dfn 序)(不是重儿子的结点遍历顺序随便,如果有子树大小相同的儿子,任选一点作为重儿子),于是整棵树变成了:

image

所有点旁边括号内就是我给这个点标上的 dfn 序,所有与重子的连边我都打上了感叹号。

你会发现,感叹号形成了一个个链(我们称之为重链),这棵树就可以抽象成:

image

是挺抽象的

有意思的是一条重链上所有点的 dfn 序是连续的,于是我们就可以把这一整棵树改成一个个区间了!

然后就可以用线段树维护重链了,每次查询完,就跳一次父亲进入另一条重链。

至于复杂度证明,我们发现每查询一次重链,是 \(\log{n}\) 的,复杂度就在于我们会跳父亲,但是每跳一次父亲,子树大小就会至少翻倍,所以最多跳 \(\log{n}\) 次父亲,于是复杂度最多就是 \(\log^2{n}\)。

至于查询一个点以其为根的子树中所有点的点权的和(或者最值)这种问题,你会发现,子树中的 dfn 序是连续的,所以只用在线段树上求该点的 dfn 序到该点 dfn 序加上该子树大小再减一的区间即可。

具体讲一下实现:

先进行一次 DFS 处理出重子,深度,子树大小,每个点的父亲。

然后再进行一次 DFS 求出该点表上的序号、所在的重链的链首(就是深度最小的那个,也是序号最小的那个)即可(记得要先遍历重子,再遍历轻儿子)。

修改和查询时,两边的两个点优先跳深度大的那个,如果发现两点在同一条链上,就结束,然后修改这两个点之间的点即可(区间修改嘛,都会吧)。

线段树的实现我还讲吗……

很简单,是吧

然后上好题:

[ZJOI2008]树的统计

送的。

[SHOI2012]魔法树

还是送的。

[USACO11DEC]Grass Planting G

相信简单的边权转点权都会吧。

由于每个点只有一个父亲(【数据删除】?),所以我们把每个点到他父亲的边的边权存在这个点上就可以了(根节点为点权零哦)。

CF165D Beard Graph

相信简单的边权转点权都会吧。

QTREE - Query on a tree

好极了,又是一道边权转点权。

Qtree1

只能我无语了。

[HAOI2015]树上操作

好啊好啊,妙极了

Water Tree

再来。

月下“毛景树”

应该,没了?(?)

标签:遍历,剖分,复杂度,树链,dfn,子树,重链,边权
From: https://www.cnblogs.com/Y2y7m/p/17426765.html

相关文章

  • Delaunay三角剖分——BW算法
    Delaunay三角剖分定义在数学和计算几何中,对于给定的平面中的离散点集P ,其Delaunay三角剖分DT()满足:空圆性:DT(P)是 唯一 的(任意四点不能共圆),在DT(P)中,任意 三角形的外接圆范围内不会有其它点存在。最大化最小角:在点集P 可能形成的三角剖分中,DT(P)所形成的三角形......
  • B. 染色(树链抛分)
    B.染色-树链剖分-比赛-衡中OI(tg.hszxoj.com)题目描述原题来自:SDOI2011给定一棵有  个节点的无根树和  个操作,操作共两类。将节点  到节点  路径上的所有节点都染上颜色;询问节点  到节点  路径上的颜色段数量,连续相同颜色的认为是同一段,例如 1......
  • hdu:How far away ?(树链剖分)
    ProblemDescriptionTherearenhousesinthevillageandsomebidirectionalroadsconnectingthem.Everydaypeolealwaysliketoasklikethis“HowfarisitifIwanttogofromhouseAtohouseB”?Usuallyithardtoanswer.Butluckilyintthisvilla......
  • 树链剖分学习笔记
    一棵树,支持:路径加单点查询一般树上链的问题使用树链剖分解决。重链剖分前置知识LCA,线段树定义重儿子:所有儿子中子树最大的儿子为重儿子重边:重儿子之间的连边重链:若干重儿子连成的链性质一棵树可以被剖成若干重链。优先遍历重儿子,所有重链的dfs序连续。重链数量不......
  • 最近公共祖先 树链剖分
    例题:洛谷P3379【模板】最近公共祖先(LCA)https://www.luogu.com.cn/problem/P3379首先是几个概念重儿子:父结点所有子树中最大的子树的根节点(只有一个或没有)轻儿子:父结点除了重儿子以外的所有子结点(没有或有很多个)重边:父结点和重儿子连的边轻边:父结点和轻儿子连的边重链:相接......
  • 【学习笔记】长链剖分
    简述在常规树链剖分中把重儿子设成\(siz\)最大的儿子,这样从根跳重链时子树大小至少减半,因此只需要\(O(\logn)\)次即可到达任何节点。考虑把关键字由\(siz\)改成子树内最大的深度\(dep\),这样的剖分方法称为长链剖分。voiddfs1(intu,intfa,intd){dep[u]=d,mxdep......
  • 长链剖分学习笔记
    一些定义重子节点表示其子节点中子树深度最大的子结点如果有多个子树最大的子结点,取其一。如果没有子节点,就无重子节点。轻子节点表示剩余的子结点从这个结点到重子节点的边为重边到其他轻子节点的边为轻边若干条首尾衔接的重边构成重链把落单的结点也当作重链,那么整棵......
  • LightOJ 1348 Aladdin and the Return Journey (树链剖分)
    树链剖分模板题。最近一直有比赛。。好长时间没写了。明显生疏了。。找个模板题熟悉一下。代码如下:#include<iostream>#include<string.h>#include<math.h>#include<queue>#include<algorithm>#include<stdlib.h>#include<map>#include<set>#include......
  • BZOJ 2243 [SDOI2011] 染色 (树链剖分)
    题目地址:BZOJ2243普通的树链剖分,用线段树维护区间段数与最左边和最右边的颜色。然后当合并区间的时候判断一下左儿子的右端与右儿子的左端是否相同,若相同,则将和减去1.同样,在迭代求值的过程中,也要记录下上条链的最顶端的颜色。代码如下:#include<iostream>#include<strin......
  • SPOJ 375 QTREE系列-Query on a tree (树链剖分)
    题目地址:SPOJ375树链剖分第一发!果然是个貌似很高级的数据结构,其实就是把树的边从树形结构转化成了线性结构,从而可以用线段树或树状数组之类的数据结构进行快速维护。从而将时间缩到n*log(2*n).这题用的线段树维护的。代码如下:#include<iostream>#include<string.h......