当前位置: 首页 > news >正文

算法与数据结构 9 - 重链剖分

引言

尽管有些题会卡重链剖分,但它仍是一种强大的树上问题处理工具。
在许多资料中,『树链剖分』默认指重链剖分,因为它用得最多。本文明确区分『重链剖分』和『树链剖分』。

重链剖分

定义

本文中『树』默认为有根树。节点的『DFN 序』默认在 DFS 时优先遍历重边。
重子节点』或『重儿子』是一个点所有子结点中,以它为根的子树最大的那个。
重边』是从某个点连向其重儿子的边。
重链』是由若干重边相连而成的链。不在任何重链上的点可以被视为包含 \(0\) 条边的重链。

实现

首先用一个 DFS 得到每个点的父亲、深度、子树大小和重儿子。

void dfs1(int u) {hson[u] = -1;siz[u] = 1;for (int j = 0; j < g[u].size(); j++) {int v = g[u][j];if (!dep[v]) {dep[v] = dep[u] + 1;fa[v] = u;dfs1(v);siz[u] += siz[v];if (hson[u] == -1 || siz[v] > siz[hson[u]]) hson[u] = v;}}
}

接着再一个 DFS 得到每个点的所在重链顶、DFN 序,以及每个 DFN 序对应的点编号。

void dfs2(int u, int t) {top[u] = t;dfn[u] = ++cnt;if (hson[u] != -1) {dfs2(hson[u], t);for (int i = 0; i < g[u].size(); i++) {int v = g[u][i];if (v != fa[u] && v != hson[u]) dfs2(v, v);}}
}

应用

维护路径信息

从两个点出发,不断跳链顶。由于同一条链上的 DFN 序是连续的,可以方便地套用维护序列的数据结构,如线段树。
下面以修改路径上节点权值、查询路径上的节点权值和为例。

void padd(int x, int y, int z) {while (top[x] != top[y]) {if (dep[top[x]] < dep[top[y]]) swap(x, y);update(1, 1, n, dfn[top[x]], dfn[x], z);x = fa[top[x]];}if (dep[x] > dep[y]) swap(x, y);update(1, 1, n, dfn[x], dfn[y], z);
}
int psum(int x, int y) {int res = 0;while (top[x] != top[y]) {if (dep[top[x]] < dep[top[y]]) swap(x, y);res += query(1, 1, n, dfn[top[x]], dfn[x]);x = fa[top[x]];}if (dep[x] > dep[y]) swap(x, y);return res + query(1, 1, n, dfn[x], dfn[y]);
}
维护子树信息

同一个子树内的 DFN 序显然也是连续的。也可以套用维护序列的数据结构。
下面以修改子树内节点权值、查询子树内节点权值和为例。

void tadd(int x, int z) {update(1, 1, n, dfn[x], dfn[x] + siz[x] - 1, z % p);
}
int tsum(int x) {return query(1, 1, n, dfn[x], dfn[x] + siz[x] - 1) % p;
}
维护路径、子树信息时换根

对于路径信息,根节点是谁没有影响。
对于子树信息,当然不能在换根后重新 DFS。考虑将新树信息映射到原树上。例如,使用差分思想,将新树的子树表示成原树某两棵子树的差。具体问题具体分析。

查询两点最近公共祖先

类似倍增,两点不断跳链顶,直到跳到同一条重链上。LCA 就是深度更小的那个点。

int lca(int u, int v) {while (top[u] != top[v]) {if (dep[top[u]] > dep[top[v]])u = fa[top[u]];elsev = fa[top[v]];}return dep[u] > dep[v] ? v : u;
}
http://www.hskmm.com/?act=detail&tid=39434

相关文章:

  • 域登录态分享(类sso)
  • Spring Cloud Gateway网关路由配置 - AlanLee
  • Alibaba Cloud Linux 4 安装docker后,修复docker的方法
  • 重构学习认知:从听讲、践行到教学的启示
  • ssh原理
  • 实现一个简易版本的IOC
  • day000 ML串讲
  • 我的学习方式破局思考 ——读《认真听讲》、《做中学》与《做教练》有感
  • cmd运行python文件
  • MPK(Mirage Persistent Kernel)源码笔记(2)--- 多层结构化图模型
  • Unity协程除了实现功能还可以增加可读性
  • 2025年TPU厂家权威推荐榜:专业TPU加纤、TPU改性生产技术实力与市场口碑深度解析
  • 作业一
  • Nginx部署星益小游戏平台(静态页面)
  • hadoop应用遇到的问题
  • Nginx程序结构及核心配置
  • 事倍功半是蠢蛋57 typora相对路径图片上传到github
  • 序列密码基本模型
  • 企业级Nginx安装部署
  • 2025 年 10 月门窗十大品牌综合实力权威推荐榜单,聚焦产能、专利与环保的实力品牌深度解析
  • 以“听”为基,以“做”为翼
  • 解码Linux文件IO之中文字库原理与应用
  • 企业级Web应用及Nginx介绍
  • 2025 年 10 月门窗十大品牌综合实力权威推荐榜单,精准检测与稳定性能兼具的行业优选解析
  • 使用EasyBlogImageForTypora将Typora上传图床改为博客园——2025/10/26最新
  • 博客1
  • 2025 年 10 月门窗十大品牌综合实力权威推荐榜单,技术实力与市场口碑深度解析
  • HarfBuzz概览汇报总结
  • 题解:P5853 [USACO19DEC] Tree Depth P
  • 2025 年 10 月门窗十大品牌综合实力权威推荐榜单,聚焦高端定制需求与全案交付能力