「IOI 2021」分糖果(线段树)

传送门

分析:

离线后对序列做扫描线。相当于扫到 \(l\)\(r + 1\) 时,添加或删除一个 \(t\) 时刻的操作。开个数组 \(a\),把 \(t\) 时刻对糖果数量的修改量记在 \(a_t\) 上,我们要支持 \(a\) 的单点修改,以及对于容量为 \(c\) 的糖果盒的询问。

有两边的限制看着不好做,考虑先去掉下界限制。发现一定有一个时刻减到 \(0\),之后不再减到 \(0\)。记 \(f(c)\) 为容量 \(c\) 的答案,记 \(g(c, i)\) 表示只考虑 \(a_i\) 开始的后缀,且可以扣到负数时的答案,那么 \(f(c) = \max(g(c, i))\)

\(a\) 的后缀和为 \(s\),那 \(g(\infty, i)\) 就是 \(s_i\)。而 \(g(c, i)\) 还要减去 \(i\) 开始的最大前缀和超过 \(c\) 的部分,也就是 \(\max(0, s_i - s_j - c)\)。因此 \(g(c, i) = \min(s_i, \min s_j + c)\)\(j \ge i\))。

我们要求 \(\max g(c, i)\)。发现只有 \(s_i\) 为后缀最大值时有用。记 \(x, y\) 分别为 \(s\) 的后缀 max 和 min,我们求的就是 \(\max(\min(x_i, y_i + c))\)。搞个线段树二分,分段做即可。时间 \(O(n \log n)\)

提交记录

posted @ 2021-08-19 16:48  alfalfa_w  阅读(309)  评论(0编辑  收藏  举报