9.20 斜率优化复习
看我之前写的狗屎:https://www.becoder.com.cn/article/11836。
当时根本就不懂斜率优化是什么。
今天真的懂了,来写总结。
1 问题转化
对于一类 dp 方程式:\(f(i) = \min \{ f(j) + A(j)*g(i)+B(j)+t(i) \}\)。可以用斜率优化。
设 \(b=f(i)-t(i)\)。把当前 dp 转移当成是一条斜率为 \(k(x)\) 的动直线(\(b\) 未知),容易知道我们需要让 \(b\) 最小。
考虑把每个 \(j\) 的转移点当成平面上的一个点,当前直线在 \(j\) 处的 \(b\) 就是转移结果。此时根据基础函数知识:
\(Y(j)=k(x)*X(j)+b\)。
那么当前转移就有“当前点数”种转移,每个点我们都能算出对应的 \(b\),取最小值即可。
换一种等价描述:将一条斜率为 \(k\) 的直线从下向上移动,碰到的第一个点处的 \(b\) 就是当前转移答案,即 \(f(i)\)。
由于现在经过了之前的一个决策点,所以 \(f(i)\) 一定能取到这个点。
2 解决方法
2.0 分讨
就是根据加入的 \(x\) 是否单调进行讨论。如果单调则有更简单的做法。
2.1 李超
我们再把问题转化一下,我们考虑把点变成直线,即:\((X(j),Y(j))\) 变成 \(y=k(j)x+b(j)\)。其中 \(k(j)=X(j),b(j)=Y(j)\)。
然后 \(y=f(i)\),\(x\) 就是和 \(i\) 有关的数,整个式子大致还原了 dp 方程式。
对于决策点,我们就在对应区间加入一条直线;转移,就查询区间内的所有线段在 \(x\) 点的取值的最小值。这个可以李超维护。
对于一般的问题,对应的区间都是全局,所以李超树可以很好写。
比如在 Machine Works 一题中,为了避免动态开点的大常数,我们考虑还是维护 \([1,n]\) 的点,离散化即可。(一开始还是对 \(d\) 排序)
2.2 最难理解的单调队列
这玩意最容易打挂最不好调(个人向),不如李超。
还是把决策点当成是点,画图得知要维护一个上凸壳。这是一个 slope 问题,如果 x 连续就可以单调队列维护相邻两个的斜率使之单调。
查询呢,我们必然从端点开始,并且不断地删除端点,必须保证以后查询一定不会使用他们。所以还要保证我们的斜率是单调的。
2.2.ex
如果斜率不单调?
还是单调队列维护凸壳,决策点二分找即可。
3 总结
李超 yyds!