重链剖分(维护树上信息)复习笔记
本文将介绍重链剖分算法。
问题的引入
看下面一道题:
有一棵根为 的树,点上有点权,进行如下操作:
- 将以 为根的子树内所有节点的点权增加 。
- 求以 为根的子树内所有节点的点权之和。
节点数 ,询问数 。
显然,本题可以简单地使用 dfs 序线段树,将树上问题转化为数列上问题。
那么如果添加两个新的操作呢?
- 将 到 的简单路径上所有节点的点权增加 。
- 求 到 的简单路径上所有节点的点权之和。
以上问题便是 洛谷 P3384 轻重链剖分。
此时 dfs 序线段树便无法解决了,需要引入一个新的算法,也就是重链剖分。
重链剖分
概念和定义
以下是重链剖分中的一些定义:
- 重儿子:对于一个非叶子节点,它的儿子中子树最大的那个节点称为它的重儿子。
- 轻儿子:对于一个非叶子节点,它的所有儿子中不是重儿子的都称为它的轻儿子。
- 重边:一个非叶子节点与它的重儿子相连的边称为重边。
- 重链:由一系列重边相连组成的链称为重链。
- 轻链:由一系列非重边相连组成的链称为轻链。
根据以上定义,显然有:
- 叶子节点没有重儿子或轻儿子(因为它没有儿子)。
- 每一条重链的起点是轻儿子。
- 所有重链互不相交,每个点只属于一条重链。
- 重链长度之和为 (因为每个点只属于一条重链)。
- 一个点到根节点经过的轻边条数最多为 。
我们定义的数组如下:
- : 的深度。
- : 的父亲。
- : 的子树大小。
- : 的重儿子编号。
- : 所在重链的顶端。
- : 的 dfs 序(注意这里的 dfs 序与普通的不同,将在 dfs2 进行讲解。)
dfs1
在第一次 dfs 中,我们需要处理出每个节点的 。
伪代码:
dfs2
在第二次 dfs 中,我们需要处理出每个节点的 ,要先 dfs2 处理重儿子再处理轻儿子。
伪代码:
数据处理
我们可以在 dfs2 中处理出在 dfn 意义下每个点的权值,然后使用线段树维护即可。
对于链上操作,我们每次找到深度较深的点,因为 dfs2 中先处理重链后处理轻链,所以重链的 dfn 是连续的,直接将这个点到重链顶端的区间进行操作,然后将这个点跳到重链顶端的父亲。
一直重复如上操作,直到两个点在同一条重链,此时两个点之间的 dfn 也是连续的,再进行一次区间操作即可。
伪代码:
本题完结撒花!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现