斜率优化DP

因为SB大佬觉得有用,于是我决定转载一下洛谷博客
%%%

优化形如f[i]=max/min(a[i]+b[j]+c[i]d[j]) j<i的DP方程,其中a[i] c[i]为只关于i的函数,b[j] d[j]为只关于b的函数,显然可以化成f[i]=max/min(b[j]+c[i]d[j])+a[i] j<i但发现由于存在c[i]d[j]与i j都有关的项,所以不能用朴素的单调队列继续优化(废话)

斜率优化

对决策点j,k(j<K)

考虑什么情况j一定不如k(以min为例)

j不如k即

b[j]+c[i]d[j]>b[k]+c[i]d[k]

移项

c[i](d[j]d[k])>b[k]b[j]

c[i]>(b[k]b[j])/(d[j]d[k])(可能会变号,取决于d[]的单调性)

由于c[i]单调递增(题设),可以得到如果当前j不如k,那么以后j也不会优于k,所以可以舍弃j,想到用单调队列进行实现

定义函数slpoe(j,k)=(b[k]b[j])/(d[j]d[k])

显然出队条件为c[i]>slope(q[head],q[head+1])(head < tail,head tail这里是闭区间,开区间+1即可)

如何维护入队时队列单调性?

发现,对于队列中相邻三项l,m,r,两个斜率a=slope(l,m),b=slope(m,r),如果a>b因为出队条件c[i]>slope(q[head],q[head+1])那么l出队时,m必然出队(c[i]>a>b) 所以单调队列的slope应该单调递增

所以x入队时

$while(head<tail &&slope(q[tail-1],q[tail])>slope(q[tail],x))$

(画画斜率可以发现维护了一个下凸包(也可能是上凸包))

这样,就可以用单调队列配上slope愉快的砍掉复杂度上一个n

关于数形结合理解,由于本人太菜,顾不做详细叙述,看看大佬们的博客吧(逃)

优化后设队头为j

f[j]=a[i]+b[j]+c[i]d[j]

c[i]d[j]+f[i]=a[i]+b[j]

可以看做一次函数解析式,-c[i]为斜率,当d[j]=0时,即为f[i],所以直线在y轴上的截距就是所求,要取min,就让f[i]尽可能小,截距尽可能小,画图(本人不会)发现是个下凸包
(具体还是看大佬们的博客吧。。)

模板

P3628

P2120

P3195

不要少项!不要少项!不要少项!

f[i]的赋值可以直接用最初的式子,不用展开,推的式子写个slope就行(不要问我为啥要写这个)

posted @   Chen_jr  阅读(37)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示