(长期更新)DP 优化 学习笔记
- 空间优化
- 时间优化
- 状态方面的优化
- 转移方面的优化
- 快速寻找决策点
- 批量转移
- 从一批状态转移来
- 转移到一批状态
纯粹的空间优化
滚动数组 & 类似滚动数组的
本质:某个时刻,某些状态现在和以后都不会再被用到了,于是让新的状态覆盖掉这些状态。
滚动数组常用取模(特殊的:奇偶)来实现。
时间优化 & 时间和空间一起优化的(综合优化)
单调队列优化 DP
作用:去除多余点 来 快速寻找决策点。
状态转移方程:
- 可能还有 只与 \(i\) 有关的数值、其他只与 \(j\) 有关的数值 和 常数 参与运算。总之这些都是定值(\(j\) 走过了,\(f _ j\) 就成定值了)。
- \(\max\) 和 \(\min\) 同理,这里以 \(\min\) 为例。
- \(l _ i\) 和 \(r _ i\) 都随 \(i\) 增大而不降(这里假定是 \(f _ 1\) 到 \(f _ n\),且 \(r _ i < i\))。
发现 \(l _ i\) 和 \(r _ i\) 都是单调不降的,\(l _ i\) 右移相当于进队,而 \(r _ i\) 右移相当于出队。于是直接用队列来维护。
前面的点显然会比后面的先出队,那么如果后面的点已经进队了且比前面的点优,这个前面的点就永远不会作为决策点了,于是直接让它出队即可。发现这样的过程形成了一个从前往后单调递增的队列,它就是单调队列。出队的过程其实就是在队尾踢点直到踢不动。队头的点即是决策点。
在线。
斜率优化 DP
作用:去除多余点 来 快速寻找决策点。
单调队列优化 DP 无法处理 \(c _ i \times c _ j\) 这种与 \(i\) 相关的和与 \(j\) 相关的乘起来的情况。这时就需要斜率优化 DP。
状态转移方程:
- \(\max\) 和 \(\min\) 同理。
下面两个方向都是在线(上面方程里和 \(j\) 有关的可以换成 \(f _ j\),总之走过了就变成定值了)。
有两个方向:
1. 李超线段树(维护直线)
应用范围更广,但速度稍慢。
去 min 推式子。
把与 \(j\) 相关的作为直线信息,把与 \(i\) 相关的作为点的信息(直线 \(x = \ldots\))
应用范围更广,但修改 2 只 log,查询 1 只 log。
可以放到树上,李超线段树合并。
2. 队列(维护凸壳)
速度较快,但限制更多。
一些细节可能搞忘了,哪天复习来补。
把与 \(j\) 相关的作为点的信息,把与 \(i\) 相关的作为直线的信息。
相当于拿一根已知斜率的直线去过每个点,看截距的最小值。那么只需要从下往上移动这个直线,看第一个过的点是哪个。
[斜率 单增 / 单减 时,可以用单调队列来维护凸壳。斜率单增且取 \(\min\) 是维护下凸壳,斜率单减且取 \(\max\) 是维护上凸壳。总之就是考虑斜率单增还是单减,取 \(\max\) 还是取 \(\min\),四种情况,画图(也许也可以在脑子里想象出图)分析。](?)
[斜率没有单调性的时候也可能可以,只要点的横坐标有单调性就可以用队列维护凸壳,找决策点时在凸壳上二分。也要注意思考是上凸壳还是下凸壳。](?)
[实现细节上,队列要保证一定有一个点在里面。](?)
[要注意开始的时候那个位置 \(0\) 的取值,不一定直接是 \(0\),要为了之后得到正确的值而取值。](?)
还有关于精度、[\(0\)](?????;斜率?????)的问题,待补。
听 xjy 说推出来的式子可以不止一种,只要斜率单调即可。
单调队列优化 DP、斜率优化 DP 的观察技巧
- 拆式子,变成能进行这两种优化的形式。
- [换 维度枚举顺序。](?)
2024.?.?
2024.10.23