1.前言
這個東西其實就是把國家集訓隊的論文照抄下來,但是由於作者會加一些自己的理解(相當於是加注釋),希望能讓原本晦澀的論文好懂一些,也方便自己復習。
由於我看得比較慢,所以這篇文章可能更新得很慢
2.保序回歸問題
偏序關系
設 \(R\) 是集合 \(S\) 上的一個二元關系,若 \(R\) 滿足:
- 自反性:\(\forall x\in S\),有 \(x\space R\space x\)
- 反對稱性:\(\forall x,y\in S\),若有 \(x\space R\space y,y\space R\space x\),則有 \(x=y\)
- 傳遞性:\(\forall x,y,z\in S\),若有 \(x\space R\space y,y\space R\space z\),則有 \(x\space R\space z\)
那么就稱為 \(R\) 為 \(S\) 上的非嚴格偏序關系,記作 \(\preceq\)
這個東西感性理解一下就行,\(oier\) 誰管這些定義?
問題描述
我們有一張 \(n\) 個點的表示偏序關系的有向圖,給定兩個代價數組 \(y\) 和 \(w\),每條邊表示連接的兩個點之間有直接的偏序關系,那么圖上兩個點滿足 \(v_i\preceq v_j\) 當且僅當在圖上有一條簡單路徑。
求數組 \(f\) 滿足 \(\forall v_i\preceq v_j\),都有 \(f_i\leq f_j\),那么最小化回歸代價:
對於 \(p\) 相同的保序回歸,我們稱之為 \(L_p\) 問題。
所以為什么要叫保序回歸問題?因為他能在保證順序(偏序關系)的情況下最小化回歸代價
一些約定
將序列 \(z\) 中不超過 \(a\) 的元素變為 \(a\),不小於 \(b\) 的元素變為 \(b\) 稱為序列 \(z\) 向集合 \(S=\{a,b\}\) 取整
點集 \(U\) 的 \(L_p\) 均值為滿足 \(\sum_{v_i\in U}w_i|y_i-k|^p(1\leq p<\infty)\) 或者 \(\max_{v_i\in U}w_i|y_i-k|\) 最小的 \(k\)
也就是如果一堆點非要選一個相同的 \(f\) 那么選哪個數會最好。
3.特殊情形下的算法
一種貪心算法
例一:題目描述
給定正整數序列 \(y,w\),求單調不減的實數序列 \(f\),最小化 \(\sum_{i=1}^nw_i(f_i-y_i)^2\)
\(n\leq 200000\)
例一:解法
本題的偏序關系就是 \(f_i\leq f_j\) 的一條鏈,先給出兩個比較重要的結論。
結論1:點集 \(U\) 的 \(L_2\) 均值為其加權平均數 \(\frac{\sum_{v_i\in U}w_iy_i}{\sum_{v_i\in U}w_i}\)
直接把平方展開之后就是二次函數的最值點。
如果有凸單調性但是更為復雜的函數最值,說不定可以讓導數為 \(0\) 然后反解出那個位置的 \(x\)
結論2:\(\forall 1\leq i<n\),如果有 \(y_i>y_{i+1}\),那么最優解一定有 \(f_i=f_{i+1}\)
證明用到了微調法和反證法,如果在最優解中 \(f_i<f_{i+1}\),那么我們選擇極小的 \(\epsilon>0\),得到的 \(f_i'=f_i+\epsilon w_{i+1},f_{i+1}'=f_{i+1}-\epsilon w_i\),你可能覺得這樣微調有點奇怪,但是這樣能讓微調的變化取決於 \(y_i\) 和 \(y_{i+1}\) 的關系,展開就知道了:
雖然我不是很懂極限,這個柿子和 \(0\) 的關系取決於一階無窮小的大小,那么微調后答案變小,所以矛盾。
回到這道題,我們考慮怎么利用這兩個結論,由於 \(f\) 取等的條件是 \(y_i>y_{i+1}\),那么我們可以維護關於 \(y\) 的單調不減的單調棧,如果已知一個集合中的點取的 \(f\) 是相同的,那么可以把這個集合合並為一個點考慮,最優取值就是其 \(L_2\) 均值,具體的算法流程是這樣的:
- 維護一個單調棧,棧內的每個元素為 \((S_i,y_i',w_i')\),分別表示這個元素代表的集合,這個集合的 \(L_2\) 均值,這個集合的 \(w_i\) 的求和。
- 每次就加入 \((\{i\},y_i,w_i)\),如果有 \(y'_{top}>y_i\),那么直接把這兩個集合合並,新集合的 \(L_2\) 均值也可以很好地算出來,那么把原來的元素刪除,再把 \((\{i\}|S_{top},\frac{y_i+y'_{top}}{w_i+w'_{top}},w_i+w'_{top})\) 加入單調棧中即可,然后繼續看這個元素能不能彈出棧頂。
- 最后 \(f_i\) 就是集合包含 \(i\) 元素的 \(L_2\) 均值(也就是 \(y'_{x}\))
上述算法的時間復雜度 \(O(n\log n)\)(因為好像要維護集合),如果能算出 \(L_p\) 均值那么是可以向 \(L_p(1\leq p<\infty)\) 擴展的。
這個算法的局限性在於結論 \(2\) 並不是一直適用的,如果換了一個偏序關系就 \(gg\) 了。
維護折線算法
他說這個方法在 \(dp\) 優化里面挺常用的,但是我怎么沒聽說過啊喂
例二:題目描述
給定一個 \(n\) 個點 \(n-1\) 條邊的有向弱連通圖,每個點有點權 \(d_i\) 和修改耗時 \(w_i\),對於每個 \(i(1\leq i\leq n)\),每次修改可以花費 \(w_i\) 的時間把 \(d_i\) 加 \(1\) 或者減 \(1\),求最少消耗多少時間使得每一條邊 \((u,v)\) 的都滿足 \(d_u\leq d_v\)
\(n\leq 3\times10^5,1\leq d_i\leq 1e9,1\leq w_i\leq 10^4\)
弱連通圖就是把有向邊換成無向邊之后原圖聯通,換句話說就是保證了原圖的樹形結構。
例二:解法
首先由於偏序關系是非嚴格的,所以最后每個點的權值一定是某一個原來的 \(d\)
考慮用樹形 \(dp\) 解決問題,設 \(g(u,i)\) 表示把點 \(u\) 變成 \(d_i\) 並且解決 \(u\) 子樹的最小花費,不難發現取決於邊的方向可以從 \(g(v,1...i)\) 或者 \(g(v,i...n)\) 轉移而來,所以維護前綴最小值 \(L_i\) 和后綴最小值 \(R_i\) 就可以做到 \(O(n^2)\) 了。
更好的做法需要結論,維護折線優化 \(dp\) 首先需要找圖像的性質,先考慮葉子節點,把 \(g,L,R\) 三個數組放在平面直角坐標上,發現斜率單調不減,因為圖畫出來是這樣的(我知道你們都懶得畫):
對於非葉節點,\(g_u\) 是若干個斜率單調不減函數的疊加(對應位置函數值相加),所以 \(g_u\) 也是一個斜率單調不減的函數。\(L_u\) 和 \(R_u\) 就是 \(g_u\) 把一個后綴\(/\)前綴變成 \(0\),所以也是斜率單調不減得函數,那么歸納地證明所有函數都斜率單調不減。
現在問題在於維護這個折線函數,對於葉節點的函數就是區間修改。那么怎么維護疊加操作呢?直接線段樹合並就行了。這個線段樹雖然帶了懶標記,但是合並的時候直接把懶標記加起來是沒問題的。
由於 \(L,R\) 只有其中之一會對祖先產生貢獻,所以 \(L,R\) 的計算可以直接在 \(g\) 的線段樹上二分並修改。時間復雜度 \(O(n\log n)\)
但是最后一步算 \(L,R\) 我好像不是特別懂誒,可能還要想一下。
UPD:好像並不是很難做,二分找到最低點之后就直接區間修改即可(打標記嘛)