没写代码,暂且不知道有多少处笔误,还需要好好理解。。
动态 dp
矩阵乘法大家都会!dp 大家都会!线段树大家都会!
一些线性 dp 可以写成矩阵乘法的形式,这里矩阵乘法可能是 ,也可能是 ,也可能是 等等,但是只要有结合律就可以。
在每个点处的转移都写成一个矩阵的形式,而要询问单独拿出来一段区间 dp 的结果,就是询问这个区间的矩阵乘积。
基于这个原理,可以用数据结构来维护区间矩阵乘法的结果。这个就是动态 dp。
一句话:将 dp 转移写成矩阵乘法,然后用数据结构维护矩阵乘积。
例题
给定 01 串,支持单点修改,区间询问单独把这个 01 串拿出来后,每次可以 或者 ,最少几次把其消为 .
线段树维护一个分治信息,大概维护一个前面有没有给自己一个进位 ,会不会给后面一个进位 ,最小代价是多少。
可以用矩阵解释,这个就是动态 dp?
P4719 "动态 DP"&动态树分治
序列上的带修最大权独立集我们都会动态 dp,现在最大权独立集上树了。
考虑从序列到树的常见套路是静态LCT重链剖分,对于一条重链直接维护一个动态 dp 的矩阵,但是轻儿子的贡献怎么算?
设 为 节点不选/选的,并且不考虑重儿子时的 dp 值是多少。
对于一条重链,如果每个节点的 都维护出来了,那么这条重链上的动态 dp 就能维护出正确的答案。
考虑到最大权独立集具体的式子,一个儿子 dp 值改变之后,对父亲的 值的修改可以直接 加减出来,那么树剖修改的时候跳重链的时候,在父亲的重链的线段树上单点修改把父亲的 值改掉就可以了。
时间复杂度大概是 ,再带一个矩阵乘法的复杂度。
游戏
树上每个节点有若干个石子,两个人轮流在树上取石子,先手可以任选一个位置开始取一个石子,接下来每个人取石子的节点必须和对方上次取石子的节点相邻。单点修改,每次修改求谁必胜。
首先先先考虑没有修改的情况:
考虑给每个树上每个石子一个节点,如果两个石子在树上相邻就连一条边。树是二分图,所以这样建图出来也是一个二分图,那么这就是一个二分图博弈,后手必胜当且仅当这个二分图有完美匹配。(为什么?)
考虑这个匹配可以直接贪心匹配,每次尽可能的让叶子往上配对,然后将叶子删掉。
于是这个等价于对于每个点记录一个 表示以 为根的子树,奇数层 偶数层的石子数,那么就有一个 .
那么存在一个匹配就当且仅当所以 非负并且 .
树剖维护 ,奇偶层分开用线段树维护即可。
保卫王国
大家都知道 最小权点覆盖集 所有点的权值之和 最大权独立集。
也就是两者互为补集。
强制一个点必须选,就把它权值设为 ,最后给最小权点覆盖集加上原先的权值即可;如果一个点必须不选,就把它权值设为 .
这样就变成了动态 dp 模板了,总权值减去最大权独立集,当然直接推最小权点覆盖的动态 dp 也可以。
ZJOI2019 Minimax 搜索
对于一个答案 ,最优的策略就是与 LCA 深度为奇数的的 ,偶数的 的 .这样就知道每个叶子应该是 还是 了。
考虑计算答案 的方案数,差分一下即为所求。
那么考虑 表示 子树内, 节点权值变 /变 /变 的集合数。注意到这个 总和是 , 是叶子个数,所以可以只记录其中两个即可。但是每次都用给 转移起来太麻烦了,直接考虑将方案数改成概率。
那么记 为 子树内使得 权值变 的概率, 表示 子树内使得 权值变 的概率。
那么每次 的时候均摊至多会有两个叶子的 和 会发生改变。
动态 dp 维护即可,有亿、小细节。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?