P4597 序列 sequence
首先考虑 \(dp\) 。
由于只需将序列改为非严格递增,那么就有一个贪心,即最终答案的数集不会变大。
为什么呢?
这是因为只有序列某一位置严格递减时,才会进行修改。
修改可以将前面的数降到和后面的数一样大,或者将后面的数提到和前面的数一样大。
而这样只会让数集变小或不变。
那么设 \(f[i][j]\) 表示将第 \(i\) 个数变为 \(a[j]\) 并使序列非严格递增的最小代价。
\(f[i][j]=\min(f[i-1][k]+|a_i-a_k|)\)
时间复杂度 \(O(n^2)\)。
无法通过此题。
为了方便理解,将 \(dp\) 数组拆为两个来看。
\(f[i][j]\) 表示前 \(i\) 个数,将第 \(i\) 个数改为 \(\le j\) 并使序列非严格递增的最小代价。
\(g[i][j]\) 表示前 \(i\) 个数,将第 \(i\) 个数改为 \(j\) 并使序列非严格递增的最小代价。
\(g[i][j]=f[i-1][j]+|a_i-j|\)
\(f[i][j]=\min_{k\le j}(g[i][k])\)
每次固定 \(i\) ,以 \(j\) 为横坐标,函数值为纵坐标,构建平面直角坐标系。
设 \(G_i\) 表示当 \(i\) 确定后的 \(g\) 函数图像, \(F_i\) 表示当 \(i\) 确定后的 \(f\) 函数图像。
\(G_1\):
\(F_1\):
\(G_2\) 可由 \(F_1\) 转移而来,即在 \(F_1\) 上加一个绝对值函数。
那么 \(F_2\) 就是
或者 \(G_2\) 是
那么 \(F_2\) 就是
可以发现,\(F_i\) 是一个斜率递增,公差为 \(1\) ,最后一段与 \(x\) 轴平行的凸函数,\(G_2\) 是一个斜率单调递增,最后一段斜率为 \(1\) 的凸函数。
而答案就是 \(G_n/F_n\) 最低点距离 \(x\) 轴的距离。
那么如何维护这两个下凸函数呢?
首先考虑计算答案时需要什么。
可以发现只有 \(a_i\) 比当前决策点小时答案会更新。
从绝对值函数的转折点开始考虑。
转折点处的函数值一定不变,因为转折点的纵坐标为 \(0\)。
转折点前的所有函数斜率 \(-1\) ,但决策点横坐标不变。
转折点后的所有函数斜率 \(+1\) ,决策点横坐标同样不变。
原函数为 \(BAGF\),加上了函数 \(JCK\),变成了函数 \(BMNO\)
那么对答案的贡献即为 \(M\) 与 \(G\) 的纵坐标之差。
而纵坐标之差可以分为 \(MA\) 与 \(NG-MA\) 来求。
由于 \(BM\) 与 \(BA\) 的斜率差为 \(1\) ,所以横坐标之差等于纵坐标之差。
由于 \(MN\) 与 \(AG\) 的斜率差为 \(1\) ,所以横坐标之差等于将 \(MN\) 向下平移到 \(A\) 时的 \(NG\) 长度。
这样全部加起来,答案就是新决策点与原决策点的纵坐标之差。
所以我们需要知道所有的 \(\leq0\) 的斜率来维护每次决策点的更新,并计算答案。
如何维护?
首先看 \(a_i\) 在原决策点右侧或原决策点位置的情况。
那就是左侧所有函数的斜率 \(-1\) ,右侧最终取完 \(\min\) 后斜率还是 \(0\)。
所以可以想到维护一个优先队列,每次插入 \(a_i\) 表示有一条与 \(x\) 轴平行的横坐标从 \(a_i\) 到 \(+\infty\) 的射线。
那么优先队列中的斜率是什么呢?
可以发现,此时优先队列中点的斜率就是其在优先队列中排名 \(-1\) 的相反数。
但是,如果相邻两个点间的斜率差 \(>1\) ,怎么表示?
那就插入一个点多次。
现在,优先队列中的斜率就变成了与当前点数值相等的最左侧的点在优先队列中的排名-1的相反数。
如果 \(a_i\) 在原决策点左侧,又该如何维护优先队列呢?
对原函数的改动还是将 \(a_i\) 左侧的函数斜率 \(+1\),右侧的函数斜率 \(-1\)。
相当于在 \(a_i\) 位置插入两个线段,因为当前位置斜率改变了 \(2\)。
就完了。
P4331
严格递增,并要求输出方案。
对于严格递增,只需要先将 \(a_i-i\) ,最后再加回去即可转化为非严格递增。
如何输出方案?
先给出结论:每一项先取 \(q.top\) ,最后做一遍后缀 \(\min\) 即可。
首先对于最后一项,取 \(q.top\) 一定存在一种最优方案。
对于前一项,如果比后一项大,不妨将其变的和后一项一样大,这样是保证最优的。
因为每个点取的都是 \(q.top\) ,而这是每个点最小的最优可能值。
如果比后一项小,那么对于这一项到第一项,以当前项的 \(q.top\) 为结尾一定是最优的。
所以每次记录下来 \(q.top\) ,最后做一遍后缀 \(\min\)即可。
练习题
ABC250G
CF865D
ARC070E
P3642 烟火表演
P4272 序列变换
ABC217H
CF1534G