斜率优化

斜率优化

在遇到形如 \(f[i]=min/max(A(i)+B(j)+C(i)D(j))\) 的式子时,我们可以考虑使用斜率优化。

考虑去除掉 \(min/max\),以 \(j\) 有关的变量为主元变化式子得到 \(C(i)D(j)+A(i)-f[i]=B(j)\),这很像 \(kx+b=y\) 的形式。于是我们对每个 \(j\) 建一个点 $ (D(j),B(j)) $,那么就是求一条斜率为 \(C(i)\) 的直线过这些点中任意一点所得到的截距的 \(min/max\)

显然,有用的 \(j\) 的点会组成一个凸包,即对于有序的 \(j\) 点组成的序列,相邻两点见的直线的斜率是单调的。

所以我们可以考虑维护这个凸包。

对于可以将 \(j\) 按照点横坐标递增顺序插入 的题来讲,可以每次将末尾不合法的点弹出,并将 \(j\) 加到末尾。这用栈或双端队列都行。若你每次求的 \(i\) 的那条直线的斜率也是单调递增的,便可以,可以用单调队列,将队头直线斜率小于当前斜率的点都弹出,然后更新答案。这样是均摊 \(O(1)\) 的。如果不单调,就二分出来序列中比 \(i\) 斜率大的位置更新。这样做是 \(O(\log n)\) 的。

如果插入的 \(j\) 的点横坐标不能递增呢?可以用李超树、平衡树等维护。

平衡树直接按照上面维护。

李超树则需要转化上面的式子。为 \(f[i]=A(i)+min/max(D(j)C(i)+B(j))\) 对于那个 \(min/max(D(j)C(i)+B(j))\),实际就是求若干一次函数 \(D(j)x+B(j)=y\)\(C(i)\) 那个点的极值。这不就李超线段树嘛。维护就好了。

斜率优化本身比较板子,难点主要在得到 DP 公式。

posted @ 2026-04-11 16:19  kilees  阅读(7)  评论(0)    收藏  举报
//