动态规划(DP)——斜率优化

形式

形如

dp[i]=max(dp[j]a[i]×b[j]+c[j])+d[i]
的dp方程
a[x],b[x],c[x],d[x]为一些与x有关的式子)
(需保证b[x]满足单调性)
如果是min,则后面的过程反过来,自己理解去。

思路

为了O(1)选出最优的j,假设dp[j]优于dp[k],且b[j]>b[k]
即,

dp[j]a[i]×b[j]+c[j]>dp[k]a[i]×b[k]+c[k]

变成
(dp[j]+c[j])(dp[k]+c[k])b[j]b[k]>a[i]

所以要求(dp[j]+c[j])(dp[k]+c[k])b[j]b[k] 斜率越大越好,用单调队列维护
把上面那个b[j]当做横坐标,(dp[j]+c[j])当做纵坐标。
维护的单调队列要使斜率要递减(保证前面的更大),画成图像就成了一个上凸包:
动态规划(DP)——斜率优化

实现

对于一个新的i,保证b[i]最大,队列的左边为head,判断head与head+1的斜率,如果head+1更优,即

(dp[head+1]+c[head+1])(dp[head]+c[head])b[head+1]b[head]>a[i]

那么就head++;
所以dp[i]就从head位置转移过来。
接下来把dp[i]添加进单调队列,把队尾tail斜率比i小的全部弹出去,即
(dp[i]+c[i])(dp[tail]+c[tail])b[i]b[tail]>(dp[tail]+c[tail])(dp[tail1]+c[tail1])b[tail]b[tail1]

那么就tail--;
最后把i放进tail里。