CF2023B Skipping 两种做法

Sol 1

考虑一定有一个到达最右边的点,使得它前面的未跳过的点的决策全部都是完成。

假设这个点是 \(k\),可以证明他前面的所有未作决策的点一定可以做决策,如果中途选择跳过点的 \(b_{i}\le k\),跳过点就一定不优。并且显然,总会有一种最优的方案是通过某一个点 \(k\) 而计算的。而一个点 \(k\) 的答案就是 \(\sum_{i=1}^{k} a_{i}-sum_{skip}\)

因此,我们枚举这个点,这时候 \(\sum_{i=1}^{k} a_{i}\) 是一个定值,因此希望求最大值,只需要求 \(sum_{skip}\) 的最小值即可。

题目中提供了两种改变所在点的方式,一种是完成任务,我们不会改变 \(sum_{skip}\) 的值,一种是跳跃到 \(b_{i}\)\(sum_{skip}\) 会增加 \(a_{i}\)。明显构成图,分别有 \((i,i-1,0),(i,b_{i},a_{i})\) 这两条边,为了求最小值,跑最短路即可。

因此我们先依照上方方式建图,跑一边最短路,算出到达每一个点的 \(sum_{skip}\) 的最小值,枚举 \(i\),用 \(\sum_{i=1}^{k} a_{i}-sum_{skip}\) 更新答案的最大值即可。

时间复杂度 \(\mathcal O(m \log n)\)

Sol 2

考虑有以下观察,就是我们绝对不可能有包含的两次跳跃。

我们假设有 \(a,b,c,d\) 从左到右四个点。

有包含指的是,我们不可能既在决策中有在 \(b\)\(c\) 之间的跳跃,也有 \(d\)\(a\) 的跳跃。

有了这个观察,我们就有跳跃不包含的限制。

因此,我们可以认为在跳跃过程中,终点是递增的。

这给予了我们做 \(dp\) 的思路,因为我们看起来好像有了转移顺序。

这里我们用一下前面做法的结论,必然有点 \(k\) 作为 \(\sum_{i=1}^{k} a_{i}-sum_{skip}\) 可以取到整体答案。

所以我们用 \(f_{i}\) 表示最后一次跳跃是到 \(i\),中途 \(sum_{skip}\) 的最小值。

有状态转移方程:

\[\begin{aligned} f_{b_{i}}=f_{i}+a_{i} \end{aligned} \]

其中 \(f_{b_{i}}\) 应取最小值。

我们可以建一个 vector 数组来存储 \(b_{i}=k\) 的所有 \(i\),然后再内部排序。

然后我们再建一个 vector 数组来存储 \(f_{i}+a_{i}\) 前缀最小值即可。

每次转移一个 \(f_{i}\) 在 vector \(f_{i}\) 中二分最后一个小于 \(i\) 的决策点即可。

计算出 \(f_{i}\) 之后,我们就在 vector \(b_{i}\) 中二分等于 \(i\) 的决策点,然后更新前缀最大值。

最后我们枚举 \(i\),把答案与 \(\sum_{i=1}^{k} a_{i}-f_{i}\) 取最大值就行了。

好了,这就是这题的两种做法。都很有意思!期待我们都在 CF div 2 中解决 D 问题!

posted @ 2025-03-04 20:28  PM_pro  阅读(16)  评论(0)    收藏  举报