斜率優化總結

2021-09-27 09:08:03 字數 1782 閱讀 4038

考慮如下\(dp\):

\(dp(i)=max/min(a(i)+b(j)+c(i)d(j))\)

\((j < i)\)

其中,a(i),c(i)只與i有關,b(j),d(j)只與j有關。

括號裡有與i,j同時有關的項,導致單調佇列優化失效,但是如果這樣的項只有乙個可以採用斜率優化。方法如下:

將此dp方程轉化為\(dp(i)-a(i)=max/min(b(j)-c(i)(-d(j)) )\)的形式。

設b=dp(i)-a(i),y=b(j),k=c(i),x=-d(j)

即\(b=y-kx\),這時,只要使b最小/最大,就能使結果最小/最大。

移項,得\(y=kx+b\),轉化為直線的形式。每計算完乙個j就可以計算出對應的x,y.

其實就是把要最優的值設為b,只和j相關的項設為y,同時相關的設為kx。

還有類似\(b=ay-kx\)的形式(兩項相關),只要轉為\(b/a=y-(k/a)*x\)即可。

以最大為例(最小類似),現在就是要在所有的(x,y)中找出一對使得b最大。

把(x,y)表示為座標系中點的形式,就是找乙個點使得斜率為k的直線經過這個點時與y軸的交點的y座標盡量大。

可以發現把斜率為k的直線放在無限高處,再向下平移,接觸到的第乙個點就是結果。

如圖:

因為要求最大值,所以只有上凸包上的點有可能成為最大值,其他點可以刪除。

這時,紅色箭頭即為b,綠色箭頭即為最優的(x,y)。dp(i)就是b+a(i)。

如果x單調,k也單調,就可以用佇列或棧來維護凸包。(時間複雜度\(o(n)\))

如果k不單調,可以在凸包上二分,找到第乙個斜率小於k的位置,並計算解。(時間複雜度\(o(nlogn)\))

如果x不單調,可以用splay維護凸包,或利用cdq分治,在每層將x,k排序,使x,k遞增。(時間複雜度\(o(nlogn)\))

例題:bzoj1911[apio2010] 特別行動隊

設 f[i] 表示將前 i 個分組的最優值,則有轉移方程式:

\(f[i]=max( f[j]+a×(c[i]-c[j])^2+b×(c[i]-c[j])+c )\)

經過化簡得到:

\(f[i]=max( f[j]+a×c[j]^2-b×c[j]-2×a×c[i]×c[j]+a×c[i]^2+b×c[i]+c )\)

設\(a(i)=a×c[i]^2+b×c[i]+c\)

\(b(j)=f[j]+a×c[j]^2-b×c[j]\)

\(c(i)=2×a×c[i]\)

\(d(j)=-c[j]\)

就可以進行斜率優化了。且x單調遞增,k單調遞減,可以使用佇列維護凸包。

**:

#include #define ll long long

ll dp[1000010];

int sz[1000010],s[1000010];

ll x[1000010],y[1000010],he=0,ta=0;

int main()

for(int i=0;i<=n;i++)

printf("%lld",dp[n]);

return 0;

}

斜率優化總結

斜率優化是用於優化一些線性dp,主要思想類似於凸包。下面來看乙個例題 hdu 3507 由題意不難想到是dp,也很容易退出轉移過程f i m in f j s i s j 2 m i 0 i 1 但是一看 n 的範圍馬上就萎了,下面來看看用斜率怎麼優化。現將推出的轉移方程化簡 f i m in f ...

斜率優化總結

題目 luogu p2365 任務安排 題解 題解 p2365 任務安排 對於此類方程 f i begin f j val i,j end 暫時忽略min和範圍得 f i f j val i,j 整理得 f j val i,j f i 令 val i,j f i g j h i 則 f j f i ...

斜率優化總結

首先,推薦乙個大佬的部落格,講解非常詳細,所以不會斜率優化的請移步這裡,本部落格主要講題目分析qwq 主要講解題目 1.hnoi2008玩具裝箱 2.zjoi2007倉庫建設 3.usaco08mar土地徵用land acquisition 4.apio2010特別行動隊 下面,開始吧。題目分析 如...