dp on 凸壳总结&gym 101806 T Touch The Sky 题解
dp on 凸壳总结&gym 101806 T Touch The Sky 题解
我也不知道这个玩意究竟叫什么。。。。
对于这样的dp问题:
\(dp_{i,j}=\min (dp_{i-1,j},dp_{i-1,j-1}+w_i)\),(for example :Touch The Sky)
求任意的\(dp_{i,j}\)。
可以发现\(dp_{i}\)形成了一个凸壳(\(dp_{i,j}-dp_{i,j-1}\geq dp_{i,j-1}-dp_{i,j-2}\))。
上述dp有两种转移:
- \(dp_{i,j}=dp_{i-1,j}\),直接复制上一个,没啥好说的。
- \(dp_{i,j}=dp_{i-1,j-1}+w_i\),其实可以这样理解:将\(dp_{i,j}\)与\(dp_{i,j-1}\)的差值与\(w_i\)取一个min。
所以我们可以
若我们维护差分数组 :\(c_j\)=\(dp_{i,j}-dp_{i,j-1}\)
则在\(c_j\geq w_i\)的部分,所有的\(dp_{i}\)都为\(dp_{i-1}\)向上移动\(w_i\)位,并向右移动一位。
我们只需要在那个维护c数组的平衡树中插入一个\(wi\)即可。同时维护前缀和。
我们回到上面的那一个问题,Touch The Sky。
这里需要有一个限制\(dp_{i-1,j-1}\leq L_i\Leftrightarrow dp_{i-1,j-1}+W_i\leq L_i+W_i=L\prime_i\)
这其实非常好办。
只需要在那个treap里删除最后一个满足上述条件的位置即可。
这样我们就可以将一个看似没有办法优化的二维dp优化到了\(O(n^2)\),是不是非常神奇!
但是有人会说:“treap也太难打了吧,这么长的代码比赛怎么来得及写啊!”。
先别着急,Touch The Sky 这题的确可以不使用treap。
我们先看看最终题目是要求什么?并不是任意的\(dp_{i,j}\)而是凸壳的最上面的那一点的横坐标!再看看\(L\prime_i\)有什么性质,对,递增,这可以保证凸壳的最高点只会升高不会降低!(为啥递增很多题解都解释的非常清楚了,这里就不多说了)
所以我们从前到后考虑,每次加入一个差分值:\(W_i\)。若\(sum> L\prime _i\),就删除最后的那一个(最大的那一个)\(prefix\ sum \leq L\prime _i\)的差分值(这里的prefix sum位再treap里维护的前缀和),可以发现就是最大的那一个(前面已经分析了\(L\prime _i\)递增)。
所以priority_queue就ok了。
代码也就十多行。