QOJ 原题链接
简要题意
设 \(S\) 为一个可重非负整数集合,假设 \(x\) 为 \(S\) 中的一个出现次数 \(\ge 2\) 的元素,你可以将 \(x\) 改成 \(x + 1\) 或 \(x - 1\)。定义 \(f(S)\) 表示对 \(S\) 进行上述操作任意次所能达到的最大 \(\operatorname{mex}\)。
给定一个长度为 \(n\) 的序列 \(a\),有 \(q\) 次询问,每次询问给定 \(l, r\),请你求出 \(f(\{a_l, a_{l + 1}, \ldots, a_r\})\)。
观察到 \(\operatorname{ans} = \max\{i \mid \sum\limits_{j = l}^r [a_j \le i] > i\}\),考虑维护这个值。
将询问离线下来再从大往小枚举 \(\operatorname{mex}\),每个询问都维护 \(b_j = \sum\limits_{i = l_j}^{r_j} [a_i \le \operatorname{mex}] - \operatorname{mex}\),当 \(b_i > 0\) 时,将 \(ans_i\) 更新。考虑 \(\operatorname{mex}\) 减少 \(1\) 时的变化,将所有包含 \(a_i = \operatorname{mex}\) 的位置 \(i\) 的询问 \(j\) 的 \(b_j\) 减少 \(1\),接着全局加上 \(1\)。
于是就是一个矩形加、查最大值的问题,可以使用 KD-Tree 做到 \(O(n \sqrt{n})\)。
由于矩形问题并不好做,考虑转成序列问题,但是问题在于每次修改的询问是零散的。
考虑解决修改区间不连续的问题,出现这个问题的原因是可能存在两个区间 \(i, j\) 满足 \(l_j \le l_i \le r_i \le r_j\)。如果不存在这样的 \((i, j)\),那么修改的区间是连续的。
一个显然的性质是无论 \(\operatorname{mex}\) 是多少,都一定满足 \(b_i \le b_j\)。 即 \(i\) 一定在 \(j\) 之后被更新。所以我们先不考虑 \(i\),在 \(j\) 找到答案之后再放入 \(i\),那么询问序列无论何时都是有序的,并且也不会影响答案的正确性。
那么现在问题就是:
- 放入 \(i\) 后怎么求 \(i\) 现在的 \(b_i\)。显然是可以使用树状数组维护的。
- 如何找到这样一个 \(i\)。考虑将询问按 \(r\) 从小到大排序,\(r\) 相同时按 \(l\) 从大到小排序。称一个区间如果不被任何答案未知的区间包含,那么这个区间为好区间。那么存在这样一个性质:对于好区间 \(i\),设上一个好区间为 \(j\),那么 \(i\) 包含 \((j + 1) \sim (i - 1)\) 中的所有区间。所以可以使用线段树求出 \(i\)。
总时间复杂度 \(O(n \log n)\),可以通过。