[反悔貪心] Add One 2

nkxjlym發表於2024-10-26

估計是全網最複雜題解。。。

反向考慮:將 \(a_i\) 進行減操作,使得每個數都小於等於 0。考慮差分,差分後將區間減轉變為單點的加減,但是這樣一來每個數都小於等於 0 的判定就變成了要判定字首和是否都小於等於 0,這不太好處理。

考慮增加一個區間加操作,對 \([l,r]\) 的區間內的 \(a_i\) 加 1,花費為 0。可以想象為透過原本的操作把 \(a_i\) 操作至非正後,又把負數全部再加回 0。這樣一來相當於透過增加一個“不優”的操作將終止條件從全部非正轉化為了全部都要是 0,方便後續討論。

看看現在問題是什麼。給定一個陣列 \(a_i\),其中有正有負。操作1(字首):\(a_1-=1\)\(a_{r+1}+=1\),花費代價 \(r\)。操作2(字尾):\(a_l-=1\),花費代價 \(n-l+1\)。操作3(調整):\(a_x+=1\)\(a_y-=1\),滿足 \(x<y\),花費為 0。透過這三個操作,將 \(a_i\) 全部變為 0,求最小代價。

幾個觀察:

首先,操作是滿足交換律的,也就是說最優解中的操作序列打亂順序後依然是最優解。

由於 \(a_i\) 中的數全部要變為 0,那麼我們不會把正數變大,不會把負數變小,也不會對 0 做任何操作。

假設沒有負數,最優方案很顯然:對每個正數做操作2直到變小至0。但有了負數之後,這樣做就不優了,這是因為負數能夠在一定程度上最佳化正數變小的開銷。舉例說,如果有一個 “ ... -1 ... +1 ...”,我們可以透過操作3,不消耗任何代價使得後面的 +1 變為 0;如果有一個 " ... +1 ... -1 ...",我們先透過對 -1 進行操作1,花費代價 r 將 -1 轉移到 \(a_1\) 去,然後就轉化成了上面的情況,再使用操作3即可。這相當於花費 r,使得前面的 +1 變為 0。具體的,假設說 +1 在位置 \(i\),-1 在位置 \(j\),如果 \(j<i\),即 -1 在 +1 前面,我們可以讓 +1 的原本的 \(n-i+1\) 的花費降低至 0;如果 \(j>i\),可以把花費降低至 \(j-1\)

有了上面的觀察,我們可以進一步轉化題目:先不考慮負數,只用操作2把所有正數變成 0 並計算花費,然後剩下一堆負數沒有用,再考慮負數能夠透過操作1、3最多挽回多少損失。一個 -1 透過操作3,可以退回右側 +1 之前的操作2的開銷;透過操作1+操作3,可以退回左側 +1 之前的操作2的開銷。

具體來說,假設說有一個 -1 在 \(j\) 的位置,它可以透過操作1和3去處理一個在 \(j\) 之前的 \(i\) 處的 +1,挽回 \(w(j)=n-i+1-(j-1)\) 的花費,也可以選擇透過操作3去處理一個在 \(j\) 之後的 \(k\) 處的一個 +1,挽回 \(w(k)=n-k+1\) 的花費。這兩個花費分別就是在左側的 +1 和在右側的 +1 的價值。

問題變成了每一個負數的抉擇:分多少 -1 給左邊,分多少 -1 給右邊?

這裡我們使用貪心策略,每一次選擇當前能夠挽回最多代價的一對 -1 和 +1。這樣的最優配對有什麼特徵?

我們發現,不論最優配對的 +1 在哪裡,其配對的 -1 一定是當前在最左邊的那個 -1(操作1花費最小,且能對最多正數做操作3)。也就是說,越靠左的 -1 越厲害,而且最優配對的 -1 一定是最左邊的 -1。

所以每一次最佳配對的 -1 都是確定的,只需要每次找到最優的 +1 ,也就是要找到使得 \(w(j)\) 最大的 j。

注意到:

  1. 越靠左的 +1 消耗的操作2的代價越大,選擇它能挽回的代價就越多。
  2. 同在左側的 +1 都需要 -1 做一次操作1,同在右側的 +1 都不需要這個操作1。

綜上,最優的 +1 一定是 -1 兩側的最左邊的兩個 +1 中的一個。比較一下選擇最優的即可。

但上述討論姑且只是在只考慮一步的情況下的最優解,如果允許先前已經配對好的 -1 重新決定配對,當前最優的 +1 可能會變化。也就是說,之前已經做出的區域性最優抉擇可能會在後面發現不是最優的,需要進行反悔

情況1: "... +1 ... -1 ... +1 ... -1 ...":先前考慮到 2 時,組成了配對 (2,1),然後在考慮到 4 時,組成了配對 (4,3),目前為止每一步配對都在當時是最優的。但現在我們知道,如果我們對於”在考慮 2 時做出的抉擇“進行反悔:讓 2 不再和 1 配對而是和 3 配對,然後失去配對的 1 由 4 接管,那麼就可以省去一個操作1(省去一個 \(i_2-1\) 的代價)。即 (2,1)(4,3) 可以反悔成 (2,3)(4,1)。如何進行反悔?

考慮進行反悔後會發生什麼。如果應用了這個反悔,我們發現:當前情況下選擇將位於 3 的 +1 下降所能挽回的最多的價值其實不是 \(n-i_3+1-(i_4-1)\) 而是 \(n-i_3+1-(i_4-1)+(i_2-1)\)。所以,原先對處於當前 -1 的左邊的 +1 做出的估價函式,可以再增加一項。

在當前考慮的 -1(i) 的左邊的 +1(j),如果它的左邊還有一個最近的一個先前抉擇好的配對 \((p,q)\),滿足 \(q<p<j<i\) 且 p 最大,那麼透過配對 \((p,j)(i,q)\),計算得新的價值函式 \(w'(j)=n-j+1-(i-1)+(p-1)\)。這個價值函式相比於先前的,能夠多挽回 \(p-1\) 的價值。

透過允許反悔,最佳化了左側 +1 的估價函式,反過來說,透過獲取更新後的價值,也相當於自動完成了對先前抉擇的反悔。

情況2:" +1 ... -1 -1 +1 ...":位於 2 的 -1 在當時選擇了右邊最近的 +1,即與位於 4 的 +1 配對成 (2,4),但顯然全域性最優解會選擇將 3 與 4 配對。這是因為,如果配對 (3,4),那麼為了消去 1 所需要的操作1,可以由 2 而不是 3 來做,最佳化了操作 1 的花費。即 (2,4)(3,1) 可以反悔成 (2,1)(3,4)。如何進行反悔?

可以仿照情況一,對能夠最佳化的 +1 的價值函式進行修改。

比如當前考慮到的 -1 位於 \(i\),且存在一個配對 \((p,q)\) 滿足 \(p<i<q\),那麼對於 \(j<p<i<q\)\(j\),透過配對 \((p,j)(i,q)\) 其價值最佳化為 \(w'(j)=n-j+1-(p-1)\),相比於之前多挽回 \(i-p\) 的價值。但這個相比於情況一難處理得多。

實際上,我們可以透過直接避免這種情況的發生來避免反悔。注意到一段連續的 -1 中的每一個與右邊最近的 +1 配對時價值相同,但是如果我們總是選擇連續段中最右邊的 -1 去跟右邊的 +1 配對,就不會發生情況2。

故我們不再每次只考慮最左邊的一個 -1,而是考慮最左邊的連續的一段 -1(內部沒有正數),那麼左邊的 +1 還是會與最左邊的 -1 配對,而右邊 +1 會與連續段的最右邊的 -1 配對。

解決了上述的兩種情況,我們可以做到:在綜合考慮當前的抉擇過去所有抉擇的反悔的情況下,每次都能找到最優的一步選擇。這歸功於我們找到了允許反悔的情況下的每一個 +1 的價值函式。這樣每次選擇價值函式最高的 +1 的貪心,最終就可以獲得最優解。

這個問題實際上可以轉化為費用流問題,上述貪心和反悔實際上是在模擬費用流的進退流過程,因此可以獲得嚴謹的正確性證明。

相關文章