【学习笔记】DSU on Tree
概述#
DSU on Tree 即树上启发式合并,重点不在“合并”,而在利用树链剖分的性质对子树问题进行复杂度正确的分治。
面对多组询问但不带修改的树上题目,可以使用 DSU on Tree 解决。
算法流程#
-
递归处理轻儿子的答案
-
递归处理重儿子的答案
-
重新遍历轻儿子子树,计算当前子树的答案
-
如果当前节点是轻儿子,重新遍历整棵子树,清除答案
发现一个节点被再次遍历当且仅当其所在的子树根为轻儿子,在这之后其所在子树大小至少扩大 倍,因此每个节点最多被遍历 次,那么总遍历次数是 ,若单个节点计算答案复杂度 ,总复杂度 。
实现如下:
void dfs1(){
// 求出重儿子
}
void add(){
// 加入一个节点的贡献
}
void del(){
// 删去一个节点的贡献
}
void insert(int u){
// 加入整棵子树的贡献
add(u);
for(int i=head[u],v;i;i=e[i].nxt){
v=e[i].to;
if(v==fa[u]) continue;
insert(v);
}
}
void erase(int u){
// 删去整棵子树的贡献
del(u);
for(int i=head[u],v;i;i=e[i].nxt){
v=e[i].to;
if(v==fa[u]) continue;
erase(v);
}
}
void dfs2(int u){
// 递归处理轻儿子答案
for(int i=head[u],v;i;i=e[i].nxt){
v=e[i].to;
if(v==fa[u]||v==son[u]) continue;
dfs2(v);
}
// 递归处理重儿子答案
if(son[u]) dfs2(son[u]);
// 重新遍历轻儿子子树,计算当前子树的答案
add(u);
for(int i=head[u],v;i;i=e[i].nxt){
v=e[i].to;
if(v==fa[u]||v==son[u]) continue;
insert(v);
}
// 如果当前节点是轻儿子,重新遍历整棵子树,清除答案
if(fa[u]&&son[fa[u]]!=u) erase(u);
}
例题#
CodeForces-600E Lomsat gelral *2300#
维护当前最多出现次数以及对应元素之和即可。
CodeForces-570D Tree Requests *2200#
一个判断方式是最多只有一种字符出现次数为奇数,那么字符权值设计成 ,记录一下每个深度的异或和即可轻松判断。
CodeForces-208E Blood Cousins *2100#
树剖求出 级祖先,变成求子树内某深度节点个数。
CodeForces-375D Tree and Queries *2400#
朴素 DSU on Tree,后缀和使用树状数组,时间复杂度 。
CodeForces-741D Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths *2900#
比较困难。
考虑改成求 为 的最长合法路径,把每个字符出现次数的奇偶设计成状态是平凡的,可以想到对每个状态维护最大深度,查询 。
问题是增加一条边如何继承重儿子的信息,发现类似全局异或这条边的值,不妨维护一个标记 表示当前全局异或的标记,这样查询和修改都是原数异或上 进行。轻儿子合并以及暴力清空时,可以用前缀异或和 计算到祖先路径上的异或和。
时间复杂度 。
CodeForces-715C Digit Tree *2700#
设 表示 路径上数字顺次拼接而成的数, 表示 路径上数字个数,那么在 位置统计答案,即要求:
由于保证存在 的逆元,移项可以得到:
这样“拼数字”的意义就转成了模意义下的加减乘除。
简单做法是点分治分别维护。
DSU on Tree 做法比较复杂。
考虑用 map
分别维护 以及 ,第一次 DFS 可以预处理到根路径上数字正序倒序得到的数字,可以快速得到一段祖先关系的路径上数字拼出的结果。
重点是考虑继承重儿子,即加入一条边 影响,不妨维护 表示当前实际值 与 map
中存储值 的关系为 。
对于维护 的 map
,增加一条边使得 ,于是得到 ,可以得到两个标记的变化。
对于维护 的 map
,发现维护的值实际上是把拼出来的数作为小数部分,那么增加一个 就是在个位增加再向前移动小数点,于是 ,得到 。
得到两个标记的变化后可以轻松计算答案。
参考资料#
作者:SoyTony
出处:https://www.cnblogs.com/SoyTony/p/Learning_Notes_about_DSU_on_Tree.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效