dp on 凸殼總結&gym 101806 T Touch The Sky 題解

Gary_2005發表於2020-11-10

dp on 凸殼總結&gym 101806 T Touch The Sky 題解

我也不知道這個玩意究竟叫什麼。。。。

對於這樣的dp問題:

d p i , j = min ⁡ ( d p i − 1 , j , d p i − 1 , j − 1 + w i ) dp_{i,j}=\min (dp_{i-1,j},dp_{i-1,j-1}+w_i) dpi,j=min(dpi1,j,dpi1,j1+wi),(for example :Touch The Sky)

求任意的 d p i , j dp_{i,j} dpi,j

可以發現 d p i dp_{i} dpi形成了一個凸殼( d p i , j − d p i , j − 1 ≥ d p i , j − 1 − d p i , j − 2 dp_{i,j}-dp_{i,j-1}\geq dp_{i,j-1}-dp_{i,j-2} dpi,jdpi,j1dpi,j1dpi,j2)。

上述dp有兩種轉移:

  • d p i , j = d p i − 1 , j dp_{i,j}=dp_{i-1,j} dpi,j=dpi1,j,直接複製上一個,沒啥好說的。
  • d p i , j = d p i − 1 , j − 1 + w i dp_{i,j}=dp_{i-1,j-1}+w_i dpi,j=dpi1,j1+wi,其實可以這樣理解:將 d p i , j dp_{i,j} dpi,j d p i , j − 1 dp_{i,j-1} dpi,j1的差值與 w i w_i wi取一個min。

所以我們可以

若我們維護差分陣列 : c j c_j cj= d p i , j − d p i , j − 1 dp_{i,j}-dp_{i,j-1} dpi,jdpi,j1

則在 c j ≥ w i c_j\geq w_i cjwi的部分,所有的 d p i dp_{i} dpi都為 d p i − 1 dp_{i-1} dpi1向上移動 w i w_i wi位,並向右移動一位。

我們只需要在那個維護c陣列的平衡樹中插入一個 w i wi wi即可。同時維護字首和。

我們回到上面的那一個問題,Touch The Sky。

這裡需要有一個限制 d p i − 1 , j − 1 ≤ L i ⇔ d p i − 1 , j − 1 + W i ≤ L i + W i = L ′ i dp_{i-1,j-1}\leq L_i\Leftrightarrow dp_{i-1,j-1}+W_i\leq L_i+W_i=L\prime_i dpi1,j1Lidpi1,j1+WiLi+Wi=Li

這其實非常好辦。

只需要在那個treap裡刪除最後一個滿足上述條件的位置即可。

這樣我們就可以將一個看似沒有辦法優化的二維dp優化到了 O ( n 2 ) O(n^2) O(n2),是不是非常神奇!

但是有人會說:“treap也太難打了吧,這麼長的程式碼比賽怎麼來得及寫啊!”。

先彆著急,Touch The Sky 這題的確可以不使用treap。

我們先看看最終題目是要求什麼?並不是任意的 d p i , j dp_{i,j} dpi,j而是凸殼的最上面的那一點的橫座標!再看看 L ′ i L\prime_i Li有什麼性質,對,遞增,這可以保證凸殼的最高點只會升高不會降低!(為啥遞增很多題解都解釋的非常清楚了,這裡就不多說了)

所以我們從前到後考慮,每次加入一個差分值: W i W_i Wi。若 s u m > L ′ i sum> L\prime _i sum>Li,就刪除最後的那一個(最大的那一個) p r e f i x   s u m ≤ L ′ i prefix\ sum \leq L\prime _i prefix sumLi的差分值(這裡的prefix sum位再treap裡維護的字首和),可以發現就是最大的那一個(前面已經分析了 L ′ i L\prime _i Li遞增)。

所以priority_queue就ok了。

程式碼也就十多行。

相關文章