1. 程式人生 > >斜率凸優化小結

斜率凸優化小結

技術 樹形 元素 .org 進行 mat 分割 best img

斜率凸優化小結

前言

很久以前考了一道叫做"林克卡特樹"的題目( 還記得被八省聯考支配的恐懼嗎?)
正解是用直線去切一個凸函數......
當時並不是很會。然而\(APIO\)講課竟然講了並且臥槽我竟然還聽懂了。
所以就回來把這個坑給填了。

斜率凸優化

當遇到關於需要恰好選取\(K\)個的\(DP\)問題的時候,
一般做法就是在\(DP\)數組上再設一維。這樣做時間代價是\(O(n)\)的。
其實不如給每次選取加一個權值\(C\)
那麽每次選取就需要付出\(C\)的代價。所以\(C\)越大選的越少,\(C\)越小選的越多。
所以?二分\(C\)即可。時間代價變為\(O(logn)\)


形象的來說,對於\(DP\)數組,取\(E\)個時的答案\(best(E)\)是一個上凸的。
所以我們用\(f(x) = Cx\)這條直線去切這個上凸包,直到\(best(K)-KC\)是最優的。
那麽此時選取的個數就是題目所需的\(K\)個了。
下面給一張圖(引用自cjfdf):
技術分享圖片

例1:[APIO2014]序列分割

題目戳這裏
可以發現,對於不在同一段的任意兩個元素\(a\),\(b\),都對答案有\(ab\)的貢獻。
所以處理出前綴和\(pre\)
那麽轉移:\(f_{i,j} = max\{f_{k,j-1} + pre_k * (pre_i - pre_k)\}\)
斜率優化不解釋,復雜度\(O(nK)\)

,可以直接通過原題。
如果\(K \leq 200\) 變為\(K \leq n\)呢? 直接斜率凸優化即可,復雜度\(O(nlogK')\)
代碼戳這裏

例2:[八省聯考2018]林克卡特樹lct

題目戳這裏
本質上就是要選擇出\(K+1\)條不相交的路徑使它們的權值和最大。
考慮樹形\(DP\)。設\(f_{u,j,0/1/2}\)分別表示\(u\)點的度數為\(0/1/2\)時的最優解。
定義\(Ans_{u,j}\)表示\(max\{f_{u,j,0/1/2}\}\)
轉移:
對於\(f_{u,j,0}\)有:

  • \(f_{u,j,0} = max\{ f_{u,j-t,0} + Ans_{v,t} \}\)

對於\(f_{u,j,1}\)有:

  • \(f_{u,j,1} = max\{ f_{u,j-t,1} + Ans_{v,t}\}\)
  • \(f_{u,j,1} = max\{ f_{u,j-t,0} + f_{v,t,1} + Edge_{u,v}\}\)
  • \(f_{u,j,1} = max\{ f_{u,j-t-1,0} + f_{v,t,0} + Edge_{u,v}\}\)

對於\(f_{u,j,2}\)有:

  • \(f_{u,j,2} = max\{ f_{u,j-t,2} + Ans_{v,t}\}\)
  • \(f_{u,j,2} = max\{ f_{u,j-t+1,1} + f_{v,t,1} + Edge_{u,v}\}\)

上述轉移復雜度\(O(nK^2)\),不夠優秀。
發現對於 表示選擇個數的第二維\(j\) 可以進行斜率凸優化。
直接斜率凸優化即可,復雜度變為\(O(nlogK')\)。實現代碼戳我。

斜率凸優化小結