Loading

The Endspeaker (Easy Version)

算法

题意没什么可以转化的,已经很明确了。

容易发现当 \(k\) 确定且要进行移除前缀操作时,一定要尽可能的使前缀更大不然一定不优。

考虑动态规划,令 \(dp_i\) 表示移除 \(a\) 数组的前 \(i\) 项所需的最小总成本。

可以发现 \(dp_i\) 可以从 \(dp_j, 0 \leq j < i\) 推出来,令 \(k\) 表示最大的 \(k\) 使得可以移除 \([j + 1, i]\) 这一前缀,如果 \(k\) 不存在则跳过这一转移。

但是注意到 \(k\) 始终不减,考虑新开一维表示当前的 \(k\)

\[dp_{i, k} = \min(dp_{j, k^{\prime}} + m - k) , 0 \leq j < i, k^{\prime} \leq k \]

这个柿子的复杂度是 \(\mathcal{O}(n^2m^2 \log m)\) 的,考虑优化。

手动模拟一下可以发现,\(k^{\prime} \leq k\) 条件带来了大量的重复计算,事实上,我们完全可以每次仅仅令 \(k = k^{\prime} + 1 \ \rm{or} \ k^{\prime}\)

现在我们的转移柿子变成了,

\[dp_{i, k} = \begin{cases} \begin{aligned} & dp_{x, k} + m - k \\ & dp_{y, k - 1} + m - k\\ \end{aligned} \end{cases} \]

显而易见的,我们需要尽可能的使得 \(x, y\) 尽量小,并且满足 \(\textrm{Sum} (x + 1, i) , \textrm{Sum} (y + 1, i) \leq b_k\) ,二分可以处理。

初始化令 \(dp_{0, 1} = 0\) ,答案为 \(\displaystyle\min_{i = 1}^{m} {dp}_{n, i}\) ,特别的,当无法转移到答案时,输出 \(-1\)

时间复杂度 \(\mathcal{O} (nm\log m)\)

这里顺手就把 \(\rm{Hard \ Version}\) 讲一下

注意到如果要统计方案数, 必须要在转移的时候更新区间而非仅仅只更新最优解

我们线段树维护区间修改, 然后统计 \(i = n\) 时的选择方案即可


考虑复习

这里只复习 \(\textrm{Easy Version}\) , 对方程式的一些优化

还是这个转移, 关于推出这个的方式, 其实更好的理解方法是, 分类成是否将 \(k\) 增加 \(1\)

\[dp_{i, k} \stackrel{\min}{\longleftarrow} \begin{cases} \begin{aligned} & dp_{x, k} + m - k, \textrm{Sum} (x + 1, i) \leq b_k \\ & dp_{y, k - 1} + m - k, \textrm{Sum} (y + 1, i) \leq b_k \\ \end{aligned} \end{cases} \]

根据定义不难发现, 不妨把 \(dp_{i, k}\) 的第二维看做一个定值, 那么 \(dp_k (i)\) 单调不降
更一般的, 对于 \(\displaystyle\varphi (i) = \min_{k = 1}^{m} {dp}_{i, k}\) , 不难发现 \(\varphi\) 函数单调不降, 但是这个没什么用

所以如果我们找出了 \(x, y\) 的取值区间, 相当于找到了转移最值

不难发现, 随着 \(i\) 增大, 如果一个 \(x\) 对于 \(i' < i\) 都有 \(\textrm{Sum} (x + 1, i') > b_k\) , 必有 \(\textrm{Sum} (x + 1, i) > b_k\) , 有单调性, 所以简单双指针维护可以做到 \(\mathcal{O} (mn)\)

代码

总结

观察题目数据可以大概构想出方程形式,

手动模拟可以找到算法劣在哪里。

这种转移, 考虑每次 \(+1\) 处理


一种当 \(dp\) 数组对应的函数单调不降 \((\)一般是由于定义, 当然也可以自己推导\()\)\(\rm{trick}\) :
直接通过维护取值区间来维护转移最值

时刻注意单调性

posted @ 2024-11-29 11:26  Yorg  阅读(35)  评论(0)    收藏  举报