[CCO 2018] Boring Lectures 加强版

下文中的题目描述可能与原题不同。

给定长度为 \(n\) 的序列 \(A\) 和整数 \(k\),定义 \(f(A) = \max\limits_{|i - j| \in [1,k]} a_i + a_j\)

\(q\) 次修改,每次将 \(a_x\) 修改为 \(y\)。你需要在所有修改前和每次修改后求出 \(f(A)\)

\(1 \leq n,q \leq 10^6\)\(1 \leq k < n\)\(1 \leq a_i \leq 10^9\)强制在线


考虑原序列的最大值,不妨设为 \(a_i\)

  • 结论 \(1\):假设 \(a_i\) 没有被选中,则 \(a_{i-k}\)\(a_{i+k}\) 也一定不会被选中。

假设选了 \(a_{i-k}\)\(a_{i+k}\) 其中的一个数,接下来选择 \(a_i\) 必然最优,矛盾。

考虑如果选择了 \(a_i\),显然再选一个 \(a_{i-k}\)\(a_{i+k}\) 中的数即可。

否则 \(a_{i-k}\)\(a_{i+k}\) 都不被选,此时剩余的左右两边是相互独立的,分治即可。


接下来考虑优化这一过程。

考虑对序列分块,块长为 \(k\),接下来刻画找最大值的过程。

我们考虑对于每一块的最大值,都尝试做上面的过程,感性理解一下,这就是答案。

首先,对于每一块的最大值,其必然能覆盖当前的块,也就是说每个值都会被考虑到。

其次,对于每个值,其必然能被附近的最大值覆盖,差不多就是对的。


我们维护每个块,使用线段树找区间最大值即可。

对于所有块,使用 map 或者 unordered_set 维护,时间复杂度 \(O(n \log n)\)

posted @ 2026-01-12 16:30  Oken喵~  阅读(5)  评论(1)    收藏  举报