f[i]=min{f[j]+a[i]|j<i}
f[i]=min{f[j]+a[j]|j<i}
f[i]=min{f[j]+a[i]+a[j]|j<i}
像上面这些 i 的信息和 j 的信息不相关的线性DP,用堆,单调栈,线段树等都可以进行优化,但是如果 i 的信息和 j 的信息相关,比如:
f[i]=min{f[j]+(a[i]−a[j])2|j<i}
就不能用普通的方法优化了,这时候需要用到斜率优化。
我们考虑上面那个DP(假设
{an}
是递增的),如果对
i
来说
f[j]+(a[i]−a[j])2<f[k]+(a[i]−a[k])2
展开移项:
f[j]+a[i]2−2a[i]a[j]+a[j]2<f[k]+a[i]2−2a[i]a[k]+a[k]2
f[j]+a[j]2−(f[k]+a[k]2)<a[i]×(2a[j]−2a[k])
令 X(i)=2a[i],Y(i)=f[i]+a[i]2 ,则:
Y(j)−Y(k)X(j)−X(k)<a[i]
然后会发现这货是斜率的形式QwQ。
令
K(k,j)=Y(j)−Y(k)X(j)−X(k)
,则
K(k,j)<a[i]→
对
i
来说,
接下来还可以推一个结论
K(j,i)<a[i] ,那么对 i 来说,i 比 j 优秀,由于{an} 递增,所以 i 将一直比j 优秀。-
K(j,i)≥a[i]
,那么
K(k,j)≥K(j,i)≥a[i]
,即对
i
来说,
k 比 j 优秀,由于{an} 递增,所以 k 将一直比j 优秀。 所以 m 个候选最优解一定满足
K(que[i−1],que[i])<K(que[i],que[i+1])(1<i<m) ,即斜率递增。那么用一个单调队列就可以维护了:
- 若 K(que[Head],que[Head+1])<a[i] ,则队首失效,删除队首。
- 此时队首是最优解,以此算出 f[i] 。
- 若 K(que[Tail−1],que[Tail])≥K(que[Tail],i) ,则队尾失效,删除队尾,加入 i 。
相信大家会发现我强调了多次
{an} 递增,实际上并不一定需要递增,如果不递增,斜率优化会更加繁琐(所以我不会),可能需要cdq分治或splay维护。
-
K(j,i)≥a[i]
,那么
K(k,j)≥K(j,i)≥a[i]
,即对
i
来说,