DP优化

一、单调队列优化

很简单,对于 dpi=min(Aj+Bi) 的状态转移方程,可以丢进单调队列,时间复杂度 O(n)

二、斜率优化

如果是对于 dpi=min(AiBj+Ci+Dj) 的状态转移方程,就单调队列不了了,因为有一项同时存在 ij

我们考虑把不和 j 有关的都丢到等式右边,那左边要么就只和 j 有关,要么和 ij 都有关。

考虑这样的一次函数 y=kx+b,稍微移项可得 b=ykx,所以我们把只跟 i 有关的都看做 b,只跟 j 有关的看做 y,同时跟 ij 有关的看做 kx

对于上面那个式子,我们先写成 fiCi=min(AiBj+Dj),所以 b=dpiCix=Bjy=Djk=Ai。因为 Ci 是定值,所以使 dpi 最小即使 b 最小,图像如下:

image

也就是你每次确定一个 ki 以后,需要寻找一个过某个点的该斜率的线,使得截距 b 最小,观察图像,这条线必然过是两条斜率分别小于 ki 和大于 ki 的直线的交点,用个单调队列维护这个凸包即可。

具体维护方法:

设第 i 个点和第 j 个点连接的直线方程斜率为 k(i,j)

1、对于队首元素,由于维护的是一个凸包,所以 k 随着 i 的增加是单调的,把 k(qj,qj+1)<kij 都弹出;

2、这条直线最先碰到的必然是最下面那个点,即队首的点,用队首转移即可;

3、对于队尾元素,同样的,因为维护的是一个凸包,所以凹进去的部分要弹出去,即弹出所有 k(qj1,qj)>k(qj,qj+1)j 即可。

e.g. [HNOI2008] 玩具装箱

三、WQS二分

对于有限制的 dp,比如 [Luogu P4983] 忘情

状态转移方程很容易得到,即 dpi=min(dpj+(sisj+1)2)s 表示 a 数组的前缀和,很显然如果没有只能分 m 段的限制,这就是个斜率优化的简单题,然而这里有一个限制,我们画出分成的段数与 ans 的图像,很显然在 m 取到最值时,这个图像是个凸的(否则你可以随便合并两个嘛),并且最高点得是 m,考虑画图分析。

image

我们画一些斜率为 k 的线,观察每一条线 y=kx+b,移项得 b=ykx,那么我们要使得 x=m 时截距 b 最大,然后我们惊奇地发现,bi 只是 yidpi 减去了 xk,也就是把转移式改成 dpi=min(dpj+(sisj+1)2)k 即可。

我们二分 k,便可以得到答案。


__EOF__

本文作者Foraino0267
本文链接https://www.cnblogs.com/vegtable-foraino/p/16286263.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   Foraino0267  阅读(51)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
点击右上角即可分享
微信分享提示