目錄
寫在前面
- ACM 訓練(復習)的時候重新學習了一下常見的 DP 轉移的優化技巧,在學習的同時也有一些自己的理解,便一並總結在這。
- 本文成文前閱讀或參照了許多大佬的博客,這些將附在文末參考文獻中。
- 若文章中出現錯誤,煩請告知。感謝您的造訪。
矩陣快速冪優化
主要是利用矩陣快速冪來優化一些線性遞推問題。高維 DP 如果某一維狀態較少也可以用矩乘優化。
這個比較普及不細講,但是注意圖的鄰接矩陣也是可以用來矩陣加速的。
例題
前綴和優化
當轉移碰到類似於 \(f_i=\sum\limits_{l\leq j\leq r}g_j\) 時,我們可以對 \(g\) 做一個前綴和,之后兩端點差分即可。同時,其中求和式可換成 \(\min\) 或 \(\max\),不過優化的適用條件更為苛刻。
另外多維 DP 有時也能用到前綴和優化,關鍵就是找到轉移式有哪一個部分是只隨着一個枚舉變量變化而變化的,通過交換枚舉順序可以做到用前綴和優化。另外,要注意取的究竟是“前綴”還是“后綴”或是中間某兩個端點,計算端點的值的時候要考慮交換 for
對循環范圍的影響。[HEOI 2013]SAO這題可能會讓你對這部分有充分了解。
例題
two-pointer 優化
也就是雙指針優化。最常見的雙指針優化是“尺取法”。雙指針優化,大概就是一個端點移動時,取最優值時另一個端點是單調移動的。
例如,我想在一個有序數組 \(a\) 中找到兩個數 \(a_i,a_j(i<j)\),使得 \(a_j-a_i\leq C\) 且 \(a_j-a_i\) 最大。那么我們移動左端點 \(i\) 時,只需找到 \(a_j\leq C+a_i\) 的最大值即可。因為數組單調,\(j\) 也可以單調移動。當然根據題目不同,指針移動的方向是不同的,但是本質上就是固定其中一個端點,最優性地移動另一個端點。
這樣我們就能省去其中一維的枚舉,起到優化復雜度的目的。
例題
決策單調性對一類 1D/1D DP 的優化
這里 xD/yD DP 意思是狀態數有 \(n^x\) 種,每個狀態的轉移有 \(n^y\) 種的 DP。而 1D/1D DP 通常長這樣
\[ f_i = \min(\max)\{f_j+w(i,j)\} \]
而決策單調性是指,對於兩個決策點 \(j\) 與 \(k(j<k)\),如果對於狀態 \(i\),決策 \(k\) 優於 \(j\),那么對於 \(\forall i′(i′>i)\) 都有 \(k\) 優於 \(j\),即從 \(k\) 轉移一定更優,\(j\) 一定不再會成為最優決策,決策是單調的,和上文提到的雙指針優化有點類似。
未經優化的 1D/1D DP 通常復雜度是 \(O(n^2)\)。這部分將圍繞 \(w(i,j)\) 不同的性質分情況來討論不同的優化方法。注意多維 DP 中某一維可能也是 1D/1D 的,那么這一維也是可以單獨拿出優化的,因此下面只討論純粹的 1D/1D DP。
在這里,筆者敘述的思路是先討論幾個常見的優化方法,之后再引出其共同點以及一些拓展。內容有一定連續性,不建議跳躍閱讀。
\(w(i,j)\) 只含 \(i\) 和 \(j\) 的項——單調隊列優化
我們不妨將轉移寫成 \(f_i = \min(\max)\{f_j+a[i]+b[j]\}\),以 \(\min\) 為例。
因為 \(a[i]\) 與 \(j\) 無關,實際上轉移就是 \(f_i = \min\{f_j+b[j]\}+a[i]\)。那么我們只要找到 \(\min\) 括號內最小的即可。
若 \(1\leq j<i\),請移步前綴和優化。而一般來說 \(j\) 都是在一個移動的區間取值的,並且隨 \(i\) 移動而移動,我們設為 \([l_i,r_i]\),\(l_i,r_i\) 單調不減。
那么我們就只需維護一個單調遞增的單調隊列,單調隊列中存放 \(f_j+b[j],j\in[l_i,r_i]\),並且對應的下標也單調遞增。對於每一個 \(i\),我們先將新增區間部分從隊尾加入單調隊列,因為需要維護單調性,如果尾部的元素大於需要加入的元素直接舍棄,因為它不可能成為最優決策點。接着考慮隊首元素是否在可轉移區間內,若不滿足就一直出隊直到找到一個滿足條件的隊首。那么此時的隊首是 \([l_i,r_i]\) 中的最小值,更新 \(f_i\)。
例題
單調隊列優化多重背包
一般的多重背包方程式通常是 \(f_{i}\) 表示容積為 \(i\) 時的最大價值。轉移大概是(其中物品種數 \(n\),容積 \(V\),第 \(i\) 個物品有 \(c_i\) 個,體積 \(v_i\),價值 \(w_i\))
for (int i = 1; i <= n; i++)
for (int k = 1; k <= c[i]; k++)
for (int j = V; j >= v[i]; j--)
f[j] = max(f[j], f[j-v[i]]+w[i]);
顯然復雜度是 \(O(V\sum c_i)\)。一種可行的優化方法是二進制分解,大致思路是將每種物品的個數基於二進制分解為 \(O(\log c_i)\) 個不同的物品,再用這些分解后的物品做 01 背包,復雜度 \(O(Vn\log c)\)。
另一種方案就是利用單調隊列來優化。大致思路就是考慮放第 \(i\) 種物品時,我們將 \(f\) 中模 \(v_i\) 同余 \(x,x\in[0,v_i)\) 的下標拿出來拼在一起記作 \(g\),即 \(g_j=f_{(j-1)v_i+x}\) 。那么實際上,原方程 \(f_j = \max\limits_{1\leq k\leq c_i}\{f_{j-v_i\times k}+w_i\times k\}\) 等價於 \(g_j = \max\limits_{1\leq k\leq c_i}\{g_{j-k}+w_i\times k\}=\max\limits_{j-c_i\leq a<j}\{g_a+w_i\times (j-a)\}\)。這個是可以單調隊列優化的。綜上復雜度變成了 \(O(Vn)\)。
例題就不給了,隨便找個多重背包模板改了交上去就好了。
\(w(i,j)\) 只含 \(i,j\) 和 \(ij\) 的項——斜率優化
將轉移寫成 \(f_i = \min(\max)\{a[i]\times b[j]+c[i]+d[j]\}\),式子中不含 \(f_j\) 是因為 \(f_j\) 可能參與了 \(b[j]\) 和 \(d[j]\) 的運算,為了方便表達就直接將 \(f_j\) 隱去了,不過這是不影響后續討論的。同時,這種形式的決策單調性的優化 \(a,b\) 需要滿足一些條件,這里以 \(a\) 單調遞減,\(b\) 單調遞增為例,至於原因以及其他適用條件,在之后的討論會給出。還是以 \(\min\) 為例。
那么現在需要的就是對於每個 \(i\),找到最優決策點 \(j\)。對於每個 \(i\),只有跟 \(j\) 有關的是變量。於是我們將原式子變形
\[ -d[j]=a[i]\times b[j]+c[i]-f_i \]
我們用線性規划來解決這個問題。用一次函數 \(y=kx+b\) 來描述這個方程。那么 \(y=-d[j],x=b[j]\),並且 \(k=a[i],b=c[i]-f_i\)。我們現在需要 \(f_i\) 盡可能小,顯然就是要 \(b=c[i]-f_i\) 盡可能大,也就是在 \(y\) 軸上的截距盡可能大。於是我們對於 \(1\sim i-1\) 間所有的 \(j\),把 \((b[j],-d[j])\) 刻畫在坐標軸上,再用 \(y=a[i]x+b\) 去做線性規划,如圖。

顯然需要截距最大時,直線必切於這些點的上凸包,於是我們只需要維護這一個上凸包即可。

而如何在 \(i\) 不斷枚舉時,在不斷有新的點加入的情況下去維護這一個上凸包呢?之前在提出問題的時候說明了,\(b[j]\) 是單調遞增的,也就是說當我的循環變量 \(i\) 往右枚舉時,新增的點會出現在所有之前的點的右邊。我們開一個單調隊列依次存下凸包上的點,單調隊列中相鄰的兩點斜率是單調遞減的。顯然如果新加入的點會導致出現下圖的情況,那么就把隊尾的點刪掉,因為它不可能再成為最優決策點。刪除之后再重復這一過程,直至不出現如下的情況。(黃點為新加入的點,其余為原凸包上的點。)

而即使維護了這個上凸包,若還是用遍歷凸包上的點來找最優決策點的話依舊是不可以的。於是這里需要決策單調性優化,之前也保證了 \(a[i]\) 是單調遞減的,如圖。那么顯然若 \(i\) 的最優決策點為 \(j\),那么 \(\forall i'\geq i\),\(i'\) 的最優決策點 \(k\) 一定滿足 \(k\geq j\)。

並且對於最優決策點,記它與之前的一個點斜率為 \(k_1\),它與之后的一個點斜率為 \(k_2\),需要滿足 \(k_1> a[i]> k_2\)。因此每當做決策前,我們先判斷隊首與次隊首的斜率是否 \(>a[i]\),若是,隊首出隊,直至隊首與次隊首連線的斜率 \(<a[i]\)。至此,隊首元素就是對於 \(i\) 時的最優決策點。
綜上,由於每個點最多只會進出隊列各一次,所以我們就可以 \(O(n)\) 解決這一問題了。
回到這一部分的最初的問題,究竟那些性質的 \(a,b\) 可以用決策單調性的斜率優化,並且原因又是什么呢?當然你可以通過畫圖來解釋,但是下文將給出一個更加普適的原理。
決策單調性適用的原理——四邊形不等式與決策單調性
在解釋斜率優化那部分的遺留問題前,我們需要先對決策單調性這一整個部分進行歸納總結。
四邊形不等式:對於任意 \(a\leq b\leq c\le d\),有 \(w(a,d)+w(b,c)\geq w(a,c)+w(b,d)\)。
注意,四邊形不等式不同於代數上的不等式。它只是一些 \(w\) 的二元函數具備的某種特殊性質。
定理:若 \(w(i,j)\) 滿足四邊形不等式,那么 1D/1D DP 是可以用決策單調性優化的。
實際上某些情況下不等號是 \(\leq\) 而不是 \(\geq\)。並且這兩者適用的 DP 以及單調性是有些許差別的,具體地
- 當四邊形不等式不等號取 \(\geq\) 時,若轉移方程是取 \(\min\) 值,那么最優決策點與 \(i\) 的移動方向相同,並且單調;
- 當四邊形不等式不等號取 \(\geq\) 時,若轉移方程是取 \(\max\) 值,那么最優決策點與 \(i\) 的移動方向相反,並且單調;
- 當四邊形不等式不等號取 \(\leq\) 時,若轉移方程是取 \(\min\) 值,那么最優決策點與 \(i\) 的移動方向相反,並且單調;
- 當四邊形不等式不等號取 \(\leq\) 時,若轉移方程是取 \(\max\) 值,那么最優決策點與 \(i\) 的移動方向相同,並且單調。
注意,這四種不同的單調性差別值得注意,由於下文為了行文方便,均以第一種情況為例,千萬不要以偏概全,對於題目要具體問題具體分析。
證明:以上述優化的第一種情形為例,即 \(f_i = \min\{f_j+w(i,j)\}\),並且 \(w\) 要滿足 \(w(a,d)+w(b,c)\geq w(a,c)+w(b,d)\)。
設 \(p_i\) 表示 \(i\) 的最優決策點是 \(p_i\)。那么有
\[f_{p_i}+w(p_i,i)\leq f_j+w(j,i)\tag{1}\]
同時,我們需要證明的式子是
\[f_{p_{i+1}}+w(p_{i+1},i+1)\leq f_j+w(j,i+1)\tag{2}\]
將 \((2)\) 式中 \(j\) 變為 \(p_i\)
\[f_{p_{i+1}}+w(p_{i+1},i+1)\leq f_{p_i}+w(p_i,i+1)\tag{3}\]
下面需要分情況討論
1. \(p_{i+1}=i\),那么顯然 \(p_{i+1}=i\geq p_i\) 的,滿足決策單調性;
2. \(p_{i+1}\neq i\),將 \((1)\) 式中 \(j\) 變為 \(p_{i+1}\),那么
\[f_{p_i}+w(p_i,i)\leq f_{p_{i+1}}+w(p_{i+1},i)\tag{4}\]
\((3)+(4)\) 得
\[w(p_{i+1},i+1)+w(p_i,i)\leq w(p_i,i+1)+w(p_{i+1},i)\]
若 \(p_i>p_{i+1}\),代入上式,可以發現不等號與原四邊形不等式不等號方向相反,顯然矛盾。因此 \(p_i\leq p_{i+1}\leq i\leq i+1\)。
綜上滿足 \(p_i\leq p_{i+1}\),即滿足決策單調性。
其余三種情況可以用同種方式證明,這里從簡略去。讀者可以自行證明。
既然如此,前文的單調隊列優化以及斜率優化均利用到了決策單調性。那它們的 \(w\) 函數都是滿足四邊形不等式的,下面給出證明。為了方便下面默認四邊形不等式是 \(\geq\) 的,並且 DP 值是取 \(\min\) 的。
對於單調隊列優化來說,\(w(i,j)=a[i]+b[j]\)。那么對於 \(i\leq j\leq p\leq q\)
\[\begin{aligned} w(i,q)+w(j,p)&=a[i]+b[q]+a[j]+b[p]\\ w(i,p)+w(j,q)&=a[i]+b[p]+a[j]+b[q] \end{aligned}\]
由於 \(a[i]+b[q]+a[j]+b[p]=a[i]+b[p]+a[j]+b[q]\)。顯然 \(w(i,q)+w(j,p)\geq w(i,p)+w(j,q)\),滿足四邊形不等式。
對於斜率優化來說,\(w(i,j)=a[i]\times b[j]+c[i]+d[j]\)。那么對於 \(i\leq j\leq p\leq q\)
\[\begin{aligned} w(i,q)+w(j,p)&=a[i]\times b[q]+c[i]+d[q]+a[j]\times b[p]+c[j]+d[p]\\ w(i,p)+w(j,q)&=a[i]\times b[p]+c[i]+d[p]+a[j]\times b[q]+c[j]+d[q] \end{aligned}\]
要使其滿足四邊形不等式,即 \(a[i]\times b[q]+c[i]+d[q]+a[j]\times b[p]+c[j]+d[p]\geq a[i]\times b[p]+c[i]+d[p]+a[j]\times b[q]+c[j]+d[q]\)。等價於
\[a[i]\times b[q]+a[j]\times b[p]\geq a[i]\times b[p]+a[j]\times b[q]\]
那么至此,\(a,b\) 適用於決策單調性的斜率優化需滿足的條件也迎刃而解了,即滿足上式即可。
通過對 \(w\) 的符號的討論,並且由排序不等式,對於上面的式子,更進一步的推論是,決策單調性的斜率優化需要滿足的條件就是
- 當 \(w\) 符號取 \(\geq\),DP 取 \(\min(\max)\) 值時,\(a\) 與 \(b\) 的單調性相反即可,只不過要根據決策點向左/向右移動來選擇單調棧/單調隊列維護。
- 當 \(w\) 符號取 \(\leq\),DP 取 \(\min(\max)\) 值時,\(a\) 與 \(b\) 的單調性相同即可,同上。
其實本質上就是使得 \(w\) 有四邊形不等式的性質。
因為內容編排的原因,至此給出決策單調性斜率優化的例題。
例題
\(w(i,j)\) 滿足四邊形不等式的更一般的情形——分治/二分數據結構
由上面的分析,我們可以得出對於 1D/1D 類 DP 的決策單調性優化是需要 \(w\) 滿足四邊形不等式的。不過之前舉例的單調隊列優化和斜率優化對於 \(w\) 的要求比較特殊,那么能不能有一種普適的做法使得讓 \(w\) 只要滿足四邊形不等式就可以優化呢。
舉例來說當 \(w(i,j)=\sqrt{j-i}\),這個式子是滿足 \(\forall a\leq b\leq c\leq d,w(a,d)+w(b,c)\leq w(a,c)+w(b,d)\)。不過式子中的 \(i,j\) 是不能像之前的情況一樣獨立出來的。於是我們考慮用別的方法來解決。
同樣,為了行文方便,均以決策點向右移動為例。
分治
當 DP 方程滿足
\[ f_i = \min(\max)\{g_j+w(i,j)\} \]
其中 \(g\) 與 \(f\) 無關。這時,可以用分治的方法來解決。
例如,考慮我們需要得到 \([L,R]\) 這個區間的 DP 值,並且備選的決策區間是 \([l,r]\)。若對於 \(MID\left(MID=\frac{L+R}{2}\right)\) 這個位置的 DP 值取最優時的決策點是 \(loc\),那么由決策單調性,\([L,MID-1]\) 的備選區間就是 \([l,loc]\),而 \([MID+1,R]\) 的備選區間是 \([loc,r]\)。這樣把問題分成兩個子問題分治遞歸下去。
而如何找到 \(loc\),方法是直接暴力掃 \([l,r]\) 中所有點作為決策點去轉移到 \(MID\) 上,找到其中的最優值。以 CDQ 分治的思想,整個算法時間復雜度是 \(O(n\log n)\) 的。
由於轉移時的 \(f\) 取值是不會受其他位置的 \(f\) 值的影響的,這樣就保證了每個 \(f\) 的計算不需要先決條件,這樣就能保證分治的正確性。
例題
二分+數據結構
而當 DP 方程滿足
\[ f_i = \min(\max)\{f_j+w(i,j)\} \]
也就是說 \(f\) 的取值是受前面別的 \(f\) 的取值的影響的,這樣分治的方法就不奏效了,這時有另外一個方法來解決——二分數據結構,通常使用二分+單調隊列/單調棧來實現。
在方法講解之前,我們需要給出一個引理。
引理:對於 \(w\) 滿足四邊形不等式的 DP 中 \(\forall i<j\),如果在 \(i\) 處決策點 \(n\) 比 \(m\) 優秀(\(m<n\)),那么在 \(j\) 處 \(n\) 同樣比 \(m\) 優秀。
證明:還是以 \(\geq\) 的四邊形不等式以及取 \(\min\) 的 DP 方程為例。
由含義 \(m<n<i<j\),那么滿足四邊不等式
\[w(m,j)+w(n,i)\geq w(m,i)+w(n,j)\tag{1}\]
又由於 \(n\) 在 \(i\) 點作為決策比 \(m\) 優,即
\[f_m+w(m,i)\geq f_n+w(n,i)\tag{2}\]
\((1)+(2)\) 得
\[f_m+w(m,j)\geq f_n+w(n,j)\]
得證。
在這之前我們所有的 DP 方法都是對於每個位置,考慮最優決策點。不過這個方法是對於每個位置,考慮其能成為哪些 DP 值的最優決策點。
由於滿足決策單調性,顯然最終每個位置的最優決策點是單調遞增的,例如(數字表示每個位置的最優決策點,下標從 0 開始)
在整個算法最開始時,由於考慮的決策點只有最初的 0,因此此時每個位置的最優決策都是 0,即
對於 1 這個點由於只能從 0 這個點轉移,因此 0 就是 1 的最優決策點,計算出 \(f_1\)。之后考慮 1 作為決策點對於哪些點來說能比 0 的決策更優。由之前引理,1 一定會是連續的一段后綴(也可能不存在),例如
而如何找到最左端這個 1,我們可以二分來解決。對於二分的位置,如果它用 1 更新更優,那么把右端點左移,查找是否有更靠左的位置,否則左端點右移。找到最優點之后,那么右邊這一段就全是 1 了。我們可以開一個三元組 \((i,l_i,r_i)\) 表示 \(i\) 這個決策點控制范圍為 \([l_i,r_i]\) 用隊列維護,這樣就不用額外地賦值了。
以此類推,2 這個點從 1 轉移,更新后續的決策點。循環把 \(1\sim n\) 做完即可。這其中,一共有三種不同的更新情形
- 隊尾區間未被完全覆蓋,這個時候顯然二分出最左端的更新位置之后,把當前隊尾的右端點更新,再把新的這個三元組加進隊尾。
- 新的元素不比任何一個更優,我們只需要在二分前做一次特判,看新的元素更新 \(n\) 這個位置是否比之前的更優,若否,那么顯然這個元素不可能成為后續的最優決策,舍掉。
- 隊尾區間能被完全覆蓋,也就是說,例如原來的最優決策點是
00112222234444666
新加入的 7 這個點能完整地覆蓋 6,如
00112222234477777
那么這時,我們只需在二分前把這種能被完全覆蓋的區間去掉就可以了,操作方法是比較隊尾元素作為決策點以及新的元素作為決策點轉移到隊尾元素控制的左端點哪一個更優,若新的元素能更優,把隊尾彈出。重復操作后就可以按照 1. 的情形二分了。
幾個要注意的小細節:
- 二分的區間的左端點是經過第三種情形處理后的隊尾元素的左端點,二分的右端點是 \(n\)。
- 情形 3 是可以邊二分邊彈出隊尾的。不過若這樣做,一定要注意計算 DP 值的時候千萬不要用后面的元素視作前面元素的決策。幾個例子
00112222234444666
當你計算 4 這個區間的 DP 值時,千萬不要拿 6 作為最優決策點來算,因為這樣就不滿足決策單調性了。所以還是建議先彈出不合法的隊尾再進行二分。 - 對於每個位置 \(i\),它的最優決策點就是隊首元素,不過如果隊首元素控制范圍的右端點在 \(i\) 前面,記得把這個隊首彈出再取新的隊首作為最優決策點。
同樣,若決策點單調向左移動,可以用單調棧維護這個過程。
其實,適用於分治的 DP 式子也可以用這個方法做,不過這個方法同樣也有一些缺陷,也就是單個 \(w\) 計算復雜度較高時,二分的復雜度會退化,也就起不到優化的目的了。
但是分治法中有一個暴力掃的過程,如果 \(w\) 可以通過上一個計算出的 \(w'\) 簡易地推導出,那么分治法就可以解決這一類問題(當然前提還是 \(g\) 和 \(f\) 互不影響)。例如[Codeforces 868F]Yet Another Minimization Problem這題就只能分治法做。
例題
小總結:
- \(f\) 與 \(g\) 無關,或者與此同時 \(w\) 不能簡易計算出,選擇分治法;
- \(w\) 能簡易計算出,選擇二分+數據結構的方法。
四邊形不等式的一點補充
這里對四邊形不等式做一些補充,以 \(\forall a,b,c,d, a\leq b\leq c\leq d, w(a,d)+w(b,c)\geq w(a,c)+w(b,d)\) 這樣的四邊形不等式為例。
我們取其中的一種特殊情況:取 \(i\leq i+1\leq j\leq j+1\),那么 \(w(i,j+1)+w(i+1,j)\geq w(i,j)+w(i+1,j+1)\ (*)\)。
同時若 \(w\) 滿足 \((*)\),那么 \(w\) 也是滿足四邊形不等式的。即四邊形不等式與 \((*)\) 式是等價條件。具體證明這里從略,感興趣的讀者可以自行證明。
另外,如果我們把 \((*)\) 式移項,得到 \(w(i+1,j)-w(i,j)\geq w(i+1,j+1)-w(i,j+1)\)。也就是說,隨着決策點的右移 \(j+1\),此時 \(w\) 的增長速率是小於 \(j\) 處的速率的。並且如果此時轉移方程取 \(\min\),顯然如果某時 \(j+1\) 比 \(j\) 優秀,那么之后不可能會有 \(j\) 比 \(j+1\) 優秀。這樣對應了之前總結的單調性規律,可以視為另一種證明。
四邊形不等式對 2D/1D DP 的單調性優化
上文說到,如果對於 1D/1D DP,如果轉移的代價函數 \(w\) 滿足四邊形不等式,如 \(\forall a,b,c,d, a\leq b\leq c\leq d, w(a,d)+w(b,c)\geq w(a,c)+w(b,d)\),那么 \(f\) 的決策點是滿足單調性的。除此之外,四邊形不等式的一些性質在優化區間 DP 也有一定的作用。
問題引出:假設有區間 DP 的轉移方程是 \(f_{l,r}=\min(\max)\{f_{l,k}+f_{k+1,r}+w(l,r)\}\),如果 \(w\) 滿足四邊形不等式以及區間單調性,那么這個式子是可以利用某些單調性優化到 \(O(n^2)\) 的。
- 四邊形不等式,還是以 \(\forall a,b,c,d, a\leq b\leq c\leq d, w(a,d)+w(b,c)\geq w(a,c)+w(b,d)\) 為例。
- 區間單調性,即 \(\forall a,b,c,d, a\leq b\leq c\leq d, w(a,d)\geq w(b,c)\),即小區間的函數值不超過包含其的大區間。並且式中的不等號應時刻與四邊形不等式的不等號方向一致。
對於不等號的方向和取 \(\min\) 還是取 \(\max\) 之間的關系,這里要說明的是當上述不等號取 \(\geq\) 時,對應的 DP 方程是要取 \(\min\) 的,並且單調性與枚舉順序相同。其余的可以參考上文決策單調性優化得出結論。下面還是以這一種為例。
先不加證明地引出兩個引理。(不證明是考慮到引理證出來意義不大,並且沒有必要。如果你感興趣可以參考《動態規划加速原理之四邊形不等式(趙爽)》這篇文章)
引理一 對於 DP 方程,\(f_{l,r}=\min\{f_{l,k}+f_{k+1,r}+w(l,r)\}\),若 \(w\) 滿足四邊形不等式和區間單調性,那么 DP 函數 \(f\) 同樣滿足四邊形不等式。
引理二 設 \(s_{l,r}\) 是 \(f_{l,r}\) 的最優決策點。如果 \(f\) 滿足四邊形不等式,那么會有 \(s_{i,j}\leq s_{i,j+1}\leq s_{i+1,j+1}\)。
四邊形不等式定理 若利用引理二的單調性,即 \(s_{i,j-1}\leq s_{i,j}\leq s_{i+1,j}\),來優化該區間 DP,其復雜度是可以降低至 \(O(n^2)\) 的。
證明:從區間 DP 的本質入手,我們考慮當區間長度為 \(\delta\) 時枚舉的量。對於每個左端點:
\(l=1\),\((l,l+\delta-1)\) 枚舉長度是 \(s_{l+1,l+\delta-1}-s_{l,l+\delta-2}=s_{2,\delta}-s_{1,\delta-1}\);
\(l=2\),枚舉長度是 \(s_{3,1+\delta}-s_{2,\delta}\);
\(l=3\),枚舉長度是 \(s_{4,2+\delta}-s_{3,1+\delta}\);
\(\vdots\)
\(l=n+1-\delta\),枚舉長度是 \(s_{n+2-\delta,n}-s_{n+1-\delta,n-1}\)。
把上式相加,總長度是 \(s_{n+2-\delta,n}-s_{1,\delta-1}\leq n\)。又由於總共有 \(n\) 個不同的 \(\delta\),因此總復雜度為 \(O(n^2)\)。
例題
事實上,更多的方程並不是長 \(f_{l,r}=\min(\max)\{f_{l,k}+f_{k+1,r}+w(l,r)\}\) 這個樣子,更多的會是 \(f_{i,j}=\min(\max)\{f_{k,j-1}+w(k+1,i)\}\)。大致意思是前 \(i\) 元素分為 \(j\) 個區間得到的最小/大價值。這里值得補充的是如果 \(w\) 滿足四邊形不等式,可以證明 \(f\) 同樣滿足四邊形不等式,同樣可以優化。
容易發現,這個方程和前文所述 1D/1D 類 DP 決策單調性優化是一樣的,因此這些 DP 會有多種優化方式。不過不同的方式優化還是有些許復雜度上的差異,請讀者自行思考。
例題
不滿足決策單調性的斜率優化
在上文,我們提到過基於決策單調性利用斜率對 DP 進行優化的方法。其大致思想是,通過把 DP 轉移方程進行變形,再把每一個轉移點抽象成二維平面上的點。用線性規划去求對應 DP 值的最值。這樣就可以貪心的去取上(或下)凸包上的點得出答案。由於這一過程遵循以下兩個單調性:
- 隨着 \(i\) 往后枚舉,平面上新加入的點均出現在已有的點集的右(或左)側,這樣新加入的點一定會在凸包上。因此可以比較加入的點和凸包邊緣的點的關系,維護凸包。整個過程復雜度可以做到 \(O(n)\);
- 隨着 \(i\) 往后枚舉,\(i\) 這一點對應的線性規划的直線的斜率是單調的。同時單調數據結構維護的凸包上的點兩兩相鄰的斜率也是單調的,因此如果隊首的點不再是 \(i\) 點的最優決策點的話,那么可以刪掉隊首,因為隊首不再可能是之后的最優決策點。同樣,這個過程復雜度也為 \(O(n)\)。
如果不滿足上述兩點,那么就不能用決策單調性 \(O(n)\) 進行優化了。為了解決這一問題,我們分別考慮下述情形。
直線斜率不單調——二分凸包
由於加入的點的橫坐標依舊是滿足單調性的,因此,維護凸包這一操作可以沿用上述操作。唯一需要考慮的就是如何在凸包上找到最優決策點。
既然詢問的直線不再滿足斜率單調,因此隊首的點不能輕易刪除,也更不能取隊首作為最優決策點了。但是由於數據結構中維護的凸包上相鄰的兩點之間斜率是單調的,那么我們可以考慮在凸包上二分,找到這樣一個位置 \(j\),使得直線可以正好相切於 \(j\) 點,那么這一點就是最優決策點。二分時注意邊界的取舍。
例題
加入點橫坐標不單調——平衡樹維護凸包/CDQ 分治
加入點橫坐標位於之前的點之間時,可以考慮用平衡樹來維護這一凸包。這樣就可以支持在 \(O(\log n)\) 的時間里維護凸包和查詢。不過相比而言,考慮到代碼復雜度,CDQ 分治實現更為常用。因此不再贅述平衡樹維護凸包的實現細節。
如果采用分治實現的話。考慮當前分治區間 \([l,r]\)。需要做的就是計算 \([l, mid]\) 這一部分轉移到 \([mid+1, r]\) 的貢獻。大致分以下幾步
- 先遞歸處理 \([l, mid]\) 這一區間;
- 對 \([l, mid]\) 區間內所有點按橫坐標排序,用決策單調性的方法維護這一區間內的上(或下)凸包;
- 之后把 \([mid+1, r]\) 區間內所有的點按詢問的直線斜率排序,同樣用決策單調性的方法去詢問;
- 遞歸處理 \([mid+1, r]\) 區間。
這樣就可以在 \(O(n\log^2 n)\) 的復雜度內解決這一問題。
優化:其實歸並排序也是分治過程,如果把快排換成歸並排序的話,就可以將復雜度優化成 \(O(n\log n)\)。
值得注意的是,處理點橫坐標不單調這一情況時也可以同時處理詢問直線斜率不單調的情況。
例題
帶權二分優化(DP 凸優化)
通常我們會遇到這樣的問題:給定 \(n\) 個元素,每個元素有不同的屬性,規定某一屬性必須選 \(k\) 個,最大/最小化價值;或者給定長度為 \(n\) 的序列,讓你恰好划分為 \(k\) 段,最大/最小化價值。令 \(g(x)\) 表示這一屬性必取 \(x\) 個(或序列恰好划分為 \(x\) 段)時,所有方案中的最大/最小價值。如果 \(g(x)\) 滿足是上凸/下凸,那么可以采用凸優化的方法優化這一問題(不限於 DP)。我們以下一題為例子。
例題
給你一個 \(n\) 個點 \(m\) 條邊的無向帶權連通圖,每條邊是黑色或白色。讓你求一棵最小權的恰好有 \(need\) 條白色邊的生成樹。
\(1\leq n\leq 50000, 1\leq m\leq 100000\)
我們設 \(g(x)\) 表示,在所有恰好有 \(x\) 條白邊的生成樹中,邊權和最小的生成樹的邊權和。顯然 \(g\) 函數是不能直接求出來的,不過我們可以大致感受到 \(g\) 函數是一個下凸函數,如下圖

圖中的最低點 \((x=4)\) 的縱坐標也就是這幅圖的最小生成樹權值和,即這幅圖的最小生成樹中恰有 4 條白邊。但其實對於 \(y=g(x)\) 上所有的點的縱坐標,只有最低點是可以利用最小生成樹算法算出結果的,其余無從計算。
那么當我們需要求解別處的 \(g\) 的取值時(如求 \(g(3)\)),我們有這樣一個思路——讓這一點成為整個圖像的最低點。
由於這一個函數下凸。那么假如用一直線 \(y=kx+b\) 去截這一圖像,聯立方程 \(\left\{\begin{aligned}y&=g(x)\\y&=kx+b\end{aligned}\right.\) 也就是 \(b=g(x)-kx\)。令 \(f(x)=b\),可以觀察出 \(f(x)\) 取最小的時候,也就是直線與 \(y=g(x)\) 相切時。如果這一切點恰好為 \(x=3\) 處的點,那么 \(f\) 的最小值就是 \(f(3)=g(3)-3k\)。因此如果我能求出恰當的斜率 \(k\) 以及對應的最小值 \(f(3)\),那么也就求出了 \(g(3)\)。

假設 \(k\) 確定,那么問題就只剩求出 \(f\) 的最小值。由於 \(f(x)=g(x)-kx\),實際意義就是恰有 \(x\) 條白邊的最小生成樹權值減去白邊數 \(\times k\)。那么我們可以將原圖內所有的白邊權值都恰好減去 \(k\),再求修改后圖的最小生成樹。那么求出來的權值就是最終的 \(f(3)\)。
那么如何求 \(k\) 呢?由於 \(y=g(x)\) 下凸,也就是斜率是單調不減的,因此可以考慮二分 \(k\) 值。如果當前 \(k\) 值求出的最小生成樹包含 \(>3\) 條白邊,那么斜率應減小,縮減二分上界。反之亦然。這樣我們就可以在 \(O(m\log m\log w)\) 的時間復雜度內解決這一問題,其中,\(w\) 為二分值域。
同樣對於其他的類似的問題,我們也可以通過類似地方法在 \(O(T(n)\log w)\) 的之間內求出想要問題的解,\(T(n)\) 為求解無 \(k\)-約束問題的時間復雜度,\(w\) 為二分值域。
這一方法有兩個遺留的小問題,這里說出並且做出解答:
- 二分值域的選擇。這一個可以根據具體問題,或者通過對凸包最大/最小斜率的估計得到;
- 可能存在整數二分時不能找出恰當的 \(k\),讓其相切於目標點。也就是比如 \(k=i\) 時,相切的點 < 目標點。\(k=i+1\) 時,相切的點 > 目標點。這一個問題可以考慮去小數二分,不過更常見的是結合題目性質(例如當坐標值一定為整數時,相鄰的兩點斜率不會為小數),取其左側或右側的結果。之前的例題便運用了這一方法,可以參考這一做法。
容易發現帶權二分其實就是將一個 \(k\)-約束最值問題,通過凸函數的性質,轉化為無約束的最值問題,從而將復雜度中的因子 \(m\) 變成對數,降低復雜度。如果最初問題是一類有約束的 DP 問題並且滿足凸性,那么就可以用這一方法優化 DP 了。
有時候最初的問題是 2D/1D DP 問題(如:\(f_{i, j}\) 表示前 \(i\) 個元素中選出符合條件的 \(j\) 個時最小/大價值),並且這一問題滿足凸函數性質,那么就可以用帶權二分優化這一 DP 變成 1D/1D 類 DP,這時候可能還可以用到上文所提到的一些優化方法將這一 DP 再進一步地優化。
例題
數據結構優化
數據結構優化 DP 實際上沒有太多總結性的東西。主要是需要根據 DP 轉移方程,適當地選取數據結構優化轉移時的枚舉、修改過程。結合數據結構本身對數據維護的的特點對當前的 DP 進行優化。常見的有樹狀數組、線段樹、平衡樹、線段樹合並、bitset 等等。
例題
參考文獻
- FlashHu,博客園,『DP的各種優化(動態規划,決策單調性,斜率優化,帶權二分,單調棧,單調隊列)』
- grannychan,博客園,『「算法總結」DP常用優化』
- ww3113306,洛谷題解,『題解 - [NOI2009]詩人小G』
- XDU_Skyline,CSDN,『動態規划專題小結:四邊形不等式優化』
- 羅勇軍,CSDN,『算法競賽專題解析(10):DP優化(1)--四邊形不等式』
- Creeper_LKF,博客園,『關於WQS二分算法以及其一個細節證明』
- HocRiser,博客園,『WQS二分題集』