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}\) 的最小值。
有状态转移方程:
其中 \(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 问题!

浙公网安备 33010602011771号