2023-07-01 开摆

CF671E Organizing a Race

考虑一组 \([L,R]\) 是否合法。

最优的策略肯定是,从 \(L\) 开始往右走,每次发现油不够了就贪心在自己这里加油。最后把所有剩下的全加在 \(R\) 上。

现在描述一下“油不够”的情况。设 \(f_x\) 表示从 \(n\) 走到 \(x\) 的油量。(可以发现,\(f\) 可能有负数)

那么,如果 \(f_x \le f_y\),就说明从 \(x\) 向左走到 \(y\) 不用额外加油。同样如果 \(f_x-k \le f_y\) 就说明如果你可以做 \(k\) 次操作你也能从 \(x\) 向左走到 \(y\)

扫描线从右往左扫描左端点,我们可以动态维护出为了保证从左往右能走过去,应该怎么加油。(一共只有 \(O(n)\) 次修改)每次修改都是对 \(f\) 的区间加减。

为了方便,我们可以认为在 \(x\) 位置操作使得 \([x,n]\) 的区间的 \(f\) 减少 \(1\)

我们设 \(f'\) 表示修改以后得到的新 \(f\)。先预先算出 \(r'\) 表示保证从左往右的情况下最远的右端点,于是要求真实的右端点不超过 \(r'\)。这时 \(f\) 的限制就可以看作是:

\[f_r \le \min_{i=l}^{r} f'_i \]

其实最远的 \(r\) 并不好找。不过我们可以快速 chk 一个区间 \([L,R]\) 是否有合法的解。具体的说,我们取出这个区间最大的 \(f\) 的位置,如果它不合法区间就无解。

证明可以讨论一下。不过我们有了这个结论后,就能线段树二分解决了。

posted @ 2023-07-01 21:24  一般通过小萌新  阅读(64)  评论(0编辑  收藏  举报