Day 13 - 树形 DP 与换根 DP
1|0树形 DP
树形
1|1基础
以下面这道题为例,介绍一下树形
例题 洛谷 P1352 没有上司的舞会。
某大学有
我们设
对于每个状态,都存在两种决策(其中下面的
- 上司不参加舞会时,下属可以参加,也可以不参加,此时有
; - 上司参加舞会时,下属都不会参加,此时有
。
我们可以通过
习题
1|2树上背包
树上的背包问题,简单来说就是背包问题与树形
现在有
一位学生要学习
数据范围:
每门课最多只有一门先修课的特点,与有根树中一个点最多只有一个父亲结点的特点类似。
因此可以想到根据这一性质建树,从而所有课程组成了一个森林的结构。为了方便起见,我们可以新增一门
我们设
转移的过程结合了树形
记点
注意上面状态转移方程中的几个限制条件,这些限制条件确保了一些无意义的状态不会被访问到。
可以证明,该做法的时间复杂度为
参考代码:
1|3习题
1|4参考资料与注释
2|0换根 DP
树形
通常需要两次
接下来以一些例题来带大家熟悉这个内容。
给定一个
不妨令
考虑状态转移,这里就是体现"换根"的地方了。令
-
所有在
的子树上的结点深度都减少了一,那么总深度和就减少了 ; -
所有不在
的子树上的结点深度都增加了一,那么总深度和就增加了 ;
根据这两个条件就可以推出状态转移方程
于是在第二次
参考代码:
2|1习题
3|0字典树
3|1定义
字典树,英文名
3|2引入
先放一张图:
可以发现,这棵字典树用边来代表字母,而从根结点到树上某一结点的路径就代表了一个字符串。举个例子,caa
。
有时需要标记插入进
3|3实现
放一个结构体封装的模板:
3|4应用
检索字符串
字典树最基础的应用——查找一个字符串是否在「字典」中出现过。
给你
题解:
对所有名字建
参考代码:
AC 自动机
维护异或极值
将数的二进制表示看做一个字符串,就可以建出字符集为
给你一棵带边权的树,求
点数不超过
题解:
随便指定一个根
那么,如果将所有
从
贪心的正确性:如果这么走,这一位为
参考代码:
维护异或和
1
,本质上是一种特殊的修改操作)。
如果要维护异或和,需要按值从低位到高位建立
一个约定:文中说当前节点 往上 指当前节点到根这条路径,当前节点 往下 指当前结点的子树。
插入 & 删除
如果要维护异或和,我们 只需要 知道某一位上 0
和 1
个数的 奇偶性 即可,也就是对于数字 1
来说,当且仅当这一位上数字 1
的个数为奇数时,这一位上的数字才是 1
,请时刻记住这段文字:如果只是维护异或和,我们只需要知道某一位上 1
的数量即可,而不需要知道
对于每一个节点,我们需要记录以下三个量:
ch[o][0/1]
指节点o
的两个儿子,ch[o][0]
指下一位是0
,同理ch[o][1]
指下一位是1
。w[o]
指节点o
到其父亲节点这条边上数值的数量(权值)。每插入一个数字x
,x
二进制拆分后在 上 路径的权值都会+1
。xorv[o]
指以o
为根的子树维护的异或和。
具体维护结点的代码如下所示。
插入和删除的代码非常相似。
需要注意的地方就是:
-
这里的
MAXH
指 的深度,也就是强制让每一个叶子节点到根的距离为MAXH
。对于一些比较小的值,可能有时候不需要建立这么深(例如:如果插入数字4
,分解成二进制后为100
,从根开始插入001
这三位即可),但是我们强制插入MAXH
位。这样做的目的是为了便于全局+1
时处理进位。例如:如果原数字是3
(11
),递增之后变成4
(100
),如果当初插入3
时只插入了2
位,那这里的进位就没了。 -
插入和删除,只需要修改叶子节点的
w[]
即可,在回溯的过程中一路维护即可。
实现:
全局加一
所谓全局加一就是指,让这棵 +1
。
形式化的讲,设
过程
我们思考一下二进制意义下 +1
是如何操作的。
我们只需要从低位到高位开始找第一个出现的 0
,把它变成 1
,然后这个位置后面的 1
都变成 0
即可。
下面给出几个例子感受一下:(括号内的数字表示其对应的十进制数字)
对应 0
边往下递归操作即可。
回顾一下 w[o]
的定义:w[o]
指节点 o
到其父亲节点这条边上数值的数量(权值)。
有没有感觉这个定义有点怪呢?如果在父亲结点存储到两个儿子的这条边的边权也许会更接近于习惯。但是在这里,在交换左右儿子的时候,在儿子结点存储到父亲这条边的距离,显然更加方便。
01-trie 合并
指的是将上述的两个
可能关于合并
其实合并 int merge(int a, int b)
函数,这个函数传入两个
过程
考虑怎么实现?
分三种情况:
- 如果
a
没有这个位置上的结点,新合并的结点就是b
- 如果
b
没有这个位置上的结点,新合并的结点就是a
- 如果
a
,b
都存在,那就把b
的信息合并到a
上,新合并的结点就是a
,然后递归操作处理 a 的左右儿子。
提示:如果需要的合并是将 a,b 合并到一棵新树上,这里可以新建结点,然后合并到这个新结点上,这里的代码实现仅仅是将 b 的信息合并到 a 上。
实现
其实
【luogu-P6018】【Ynoi2010】Fusion tree。
给你一棵
需要支持以下操作。
- 将树上与一个节点
距离为 的节点上的权值 。这里树上两点间的距离定义为从一点出发到另外一点的最短路径上边的条数。 - 在一个节点
上的权值 。 - 询问树上与一个节点
距离为 的所有节点上的权值的异或和。
对于
保证任意时刻每个节点的权值非负。
题解:
每个结点建立一棵
可以使用在每一个结点上设置懒标记来标记儿子的权值的增加量。
参考代码:
【luogu-P6623】【省选联考 2020 A 卷】树。
给定一棵
设
表示树上
请你求出
题解:
考虑每个结点对其所有祖先的贡献。
每个结点建立
参考代码:
可持久化字典树
参见 可持久化字典树。
__EOF__

本文链接:https://www.cnblogs.com/So-noSlack/p/18312660.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
本文来自博客园,作者:So_noSlack,转载请注明原文链接:https://www.cnblogs.com/So-noSlack/p/18312660
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
2023-07-20 第十节 动态规划 - 2