重链剖分
算法相关
定义
- 重儿子:表示其所有儿子中子树大小最大的儿子。如果有多个则任取其一。
- 轻儿子:所有不是重儿子的儿子都是轻儿子。
- 重边:重儿子与其父亲之间的边为重边。
- 轻边:轻儿子与其父亲之间的边为轻边。
- 重链:若干条首尾衔接的重边构成重链。
性质
- 重儿子不一定唯一,但确定重儿子后重链剖分唯一。
- 一条重链总是从轻儿子开始,其余点为重儿子。
- 一条重链的 dfs 序连续。
- 一棵子树的 dfs 序连续。
- 任意点 \(x\) 到其链头 \(top_x\) 的 dfs 序连续,且深度小的点 dfs 序小。
- 从任意点 \(x\) 出发到根节点,中间经过的不同的重链至多 \(\log n\) 条(切换重链子树大小起码翻倍)。
- 树上任意一条路径 \((x, y)\) 总是可以由不超过 \(\log n\) 段重链的子链拼接而成。
流程
两次 dfs。第一次求出所有点的重儿子,第二次 dfs 优先走重儿子再走轻儿子。这样的目的是让重链的 dfs 序连续。
习题
CSES 2134 Path Queries II
模板。
P3384 【模板】重链剖分 / 树链剖分
模板。
P3379 【模板】最近公共祖先(LCA)
模板。
P2590 [ZJOI2008] 树的统计
模板。
P2146 [NOI2015] 软件包管理器
思路
阅读理解题。题意可以转化为链改、链查和子树查。
P3038 [USACO11DEC] Grass Planting G
思路
模板。边权可以下放到深度更大的端点上。链查询时要将 dfs 序加一。
P1505 [国家集训队] 旅游
模板。
P4315 月下“毛景树”
模板。
P2486 [SDOI2011] 染色
简要题意
链推平,链查询颜色段数。
思路
线段树上记录区间的颜色段数,那么我们需要维护 \(lc, rc, res\) 表示线段树上区间的左端点颜色、右端点颜色和颜色段数。这样是好合并的。对于链查询,可以维护左链和右链信息,其合并方法是类似于线段树上的信息合并的。
P3976 [TJOI2015] 旅游
简要题意
记路径 \(u \rightsquigarrow v\) 对应的点的序列是 \(\{p_i\}_{i = 1} ^ k\),多次询问:
此外还有链修改。
思路
对于每个区间都维护答案信息,则在线段树上需要维护 \(mn, mx, res\) 表示线段树上区间的最小、最大值和从左到右的答案。但是这样会有问题,设有路径 \(u \rightsquigarrow v\),点 \(u, v\) 的 LCA 为 \(k\),则 \(u \rightsquigarrow k\) 和 \(v \rightsquigarrow k\) 的其中一个路径是向下的。这里向下的定义是路径指向深度增大的方向(向上同理)。于是为了信息的完备性,我们需要额外维护 \(Res\) 表示线段树上区间从右往左的答案。这样我们查询一个向上的子路径时使用 \(res\) 信息,向下的子路径使用 \(Res\) 信息即可。
P4116 Qtree3
简要题意
单点修改,查询 \(1 \rightsquigarrow u\) 第一个非 \(0\) 位置。
思路
考虑直接以 \(1\) 为根,这样只需要 \(u\) 一直向上跳。那么对于只需要每一次跳到链顶时找到这一段里面 dfs 序最小的非 \(0\) 位置,可以在区间上线段树二分。
P3313 [SDOI2014] 旅行
思路
对于每一种宗教维护一棵线段树,\(rt_i\) 表示宗教 \(i\) 线段树的根节点。一种解决方法是使用动态开点线段树,build 时创建 \(O(n \log n)\) 个节点,\(Q\) 次修改共增加 \(O(Q \log n)\) 个节点,可行。另一种思路是使用分块。维护 \(sum_{c, pos}\) 表示宗教 \(c\) 在第 \(pos\) 个块的权值和,\(mx_{c, pos}\) 表示宗教 \(c\) 在第 \(pos\) 个块的权值最大值。
P7735 [NOI2021] 轻重边
思路
初始时给每个点随便赋 \(1 \sim n\) 的不同权值,\(col\) 表示颜色。对于操作 \(1\),每次将 \(col \to col + 1\),将 \(a \to b\) 的路径所有点染色为 \(col\)。只有 \(a \to b\) 路径上的边两个端点同色,路径上的点和路径外的邻接点颜色一定不同。则重边为两端颜色相同的边,轻边为两端颜色不同的边。操作 \(2\),转化为统计 \(a \to b\) 路径上连续相同的颜色段中重边的数量,线段树维护,类比 P2486 [SDOI2011] 染色。

浙公网安备 33010602011771号