一類利用佇列優化的DP

2022-06-28 06:24:13 字數 2525 閱讀 8021

這是乙個\(o(n^2)\)的狀態和轉移方程:

\[f(i,j)=\left\

f(i-1,j-1)+k \ (1\leq j)\\

\max_ (j=1)

\end

\right.\]

這個方程目測是\(\theta(n^2)\)的,但是實際上,上面的那個方程只是把陣列整體位移了,下面的方程只是在位移後的陣列開端添上了乙個數,這個完全可以通過佇列來實現,\(+k\)的操作,用乙個整體的差分量就能實現,時間複雜度\(o(n)\)。這個方法最偉大的一點在於,它的複雜度比狀態維度還要低一維,這是讓人難以想到這種方法的一大原因。

\(n<=5000, m<=1e7\).顯然當兩種顏色的 a 相等的時候,它們完全等價,所以我們建乙個桶 \(b_i\) 表示長度限制為 i 的顏色個數,再設\(f_\)表示 dp 到了 i 號格仔,當前顏色的長度限制是 j (其實是有點 hash 的表示顏色),當前顏色已經連續了 k 個,則狀態轉移方程為:

\[f(i,j,k)=\left\

f(i-1,j,k-1) \ (1\leq k)\\

b_j\sum_} + (b_j-1)\sum_ (j=1)

\end

\right.\]

這個狀態狀態轉移方程上面和下面各是\(\theta(n^3)\)的,但是我們可以發現這個轉移方程,上面的可以用佇列來實現整體位移,下面的可以對每個佇列維護乙個和,再維護一下總和,就能實現\(\theta(n^2)\)了,主要**如下:

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

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

for (int j = 1; j <= n; j++)

for (int j = 1; j <= n; j++) }

}fout << lastsum << endl;

實現難度不大,主要難度在於設出狀態和方程,因為這個狀態有三維,很多時候我們就預設它的時間複雜度大於等於三次方,而這題偏偏又很容易得到只有兩維的狀態設定,很多人以為「肯定不如二維的狀態設定」,但實際上,這個三維的狀態可以優化到二次方,而這個二維的狀態設定沒法實現\(\theta(1)\)的轉移

\(n<=2e5,m<=20\).假設 dp 到了前 i 個點,當前的兩個子串行,乙個肯定有乙個以 i 號字串結尾,我們只需要存另乙個子串行以什麼結尾;而子串行的長度都相同,說明我們只關心這個子串行最後乙個串是哪乙個。設\(f[i][j]\)表示,dp 到了前 i 個點,乙個子串行的結尾是 i,另乙個子串行的結尾是 j 時的最短長度。綜合把 i 接到 i-1 上 和把 i 接到 i-1 之前的兩種情況,可以得到狀態轉移方程:

\[f(i,j)=\left\

\min\ \ (j=i-1)\\

f(i-1,k)+\text(i-1,i)(else)

\end

\right.\]

這個狀態轉移方程本身已經很難想到了,需要很熟稔的分類討論的能力。優化上,可以使用棧——上面那東西是整體加法,下面那東西是在棧底追加乙個值。考慮這個 min 怎麼\(\theta(1)\)求:對於 cost 相等的 k ,顯然它們是等價的。所以把已有的字串倒序放進乙個 trie 裡面,查詢時正著順著 \(s_i\) 走,每到乙個點用\(m-dep+f_x\)更新答案,其中\(f\)是樹上字首最小值,這樣會有重複情況,但是顯然不影響。用整體差分就能實現 f 值的修改。

這個是國冬模擬費用流的第二題,居然被搬來了五校聯考。。。

首先使用微擾法,把球和洞畫成兩排,把每個球連向它的洞,顯然這些連線不能相交,這就及其有利於我們進行 dp。把球和洞擺成一排並排序,設\(f[i][i]\)表示,當 \(j>0\)時表示剩下確定選下了 \(-j\)個洞待匹配的最小代價;當 \(j<0\)時表示 dp 到了第 \(i\) 個位置、剩下多少個球還待匹配的、費用提前計算的代價(提前減去絕對值函式的部分呀),那麼當前位置是個球的時候,狀態轉移方程是:

\[f(i,j)=f(i-1,j+1)+\left\

-pos_i \ (j>0)\\

pos_i (else)

\end

\right.\]

當目前位置是個洞的時候,狀態轉移方程就是:

\[f(i,j)=min(f(i-1,j),f(i-1,j-1)+\left\

-pos_i \ (j<0)\\

pos_i (else)

\end)

\right.\]

然後把第二個式子分析一下,發現當且僅當\(j=0\)的時候需要取 min, 其他時候只需要直接取右手邊的作為最小值即可,所以我們把 dp 陣列切成三段,下標是負的一段,0一段,正的一段,就可以實現 \(\theta(n)\)。評測記錄

總結:有的時候轉移的複雜度比較大/狀態的維度比較大的時候,我們不妨退而求其次,通過把狀態公升一維的代價把轉移降低一維,也許就可以通過佇列優化,反而能優化掉一維。

一類巧妙利用利用失配樹的序列DP

求長度為 text 的包含給定連續子串 text 的 0 1 串的個數。t 15 通常來說這種題目應該立刻聯想到狀壓 dp 與取反集 這樣就不用考慮大量重複情況的容斥問題。設 f 表示前 i 個字元 最後 t 個字元為 s 不包含給定連續子串的情況數,狀態轉移方程簡單不述。時間複雜度 theta 2...

一類巧妙利用利用分治的序列求值

這個方法經常用於這類問題 給定序列 a 並定義基於序列 a 的函式 f l,r 求 sum limits f l,r 這個方法的核心做用是 將不滿足可減性的求值,變成只需要可以區間拼合 即滿足區間可加性 的求值式子。拆成每個點的貢獻處理。從左到右推進端點 r 開乙個資料結構維護對於當前每個 l 的函...

一類斜率優化的dp(特有性質 只能連續,不能交叉)

hdu3480 給定乙個有n個數的集合,將這個集合分成m個子集,要求子集的並等於全集 求花費最小。花費為該子集的 最大數 最小數 的平方。我們將n個數排序,a b c d 那麼不可能a,c乙個集合,b,c乙個集合 明顯a,b乙個集合,c,d乙個集合更優 也就是說某乙個數只能和它前面的連續幾個數合起來...