因为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就行(不要问我为啥要写这个)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了