斜率優化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\)
關於數形結合理解,由於本人太菜,顧不做詳細敘述,看看大佬們的部落格吧(逃)
優化後設隊頭為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]儘可能小,截距儘可能小,畫圖(本人不會)發現是個下凸包
(具體還是看大佬們的部落格吧。。)
模板
不要少項!不要少項!不要少項!
f[i]的賦值可以直接用最初的式子,不用展開,推的式子寫個slope就行(不要問我為啥要寫這個)