[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)\)。

浙公网安备 33010602011771号