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(dpi−1,j,dpi−1,j−1+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,j−dpi,j−1≥dpi,j−1−dpi,j−2)。
上述dp有两种转移:
- d p i , j = d p i − 1 , j dp_{i,j}=dp_{i-1,j} dpi,j=dpi−1,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=dpi−1,j−1+wi,其实可以这样理解:将 d p i , j dp_{i,j} dpi,j与 d p i , j − 1 dp_{i,j-1} dpi,j−1的差值与 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,j−dpi,j−1
则在 c j ≥ w i c_j\geq w_i cj≥wi的部分,所有的 d p i dp_{i} dpi都为 d p i − 1 dp_{i-1} dpi−1向上移动 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 dpi−1,j−1≤Li⇔dpi−1,j−1+Wi≤Li+Wi=L′i
这其实非常好办。
只需要在那个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 L′i有什么性质,对,递增,这可以保证凸壳的最高点只会升高不会降低!(为啥递增很多题解都解释的非常清楚了,这里就不多说了)
所以我们从前到后考虑,每次加入一个差分值: W i W_i Wi。若 s u m > L ′ i sum> L\prime _i sum>L′i,就删除最后的那一个(最大的那一个) p r e f i x s u m ≤ L ′ i prefix\ sum \leq L\prime _i prefix sum≤L′i的差分值(这里的prefix sum位再treap里维护的前缀和),可以发现就是最大的那一个(前面已经分析了 L ′ i L\prime _i L′i递增)。
所以priority_queue就ok了。
代码也就十多行。