P13693
jly 讲的分治做法。
首先这个可划分的段数 \(k\) 的数量显然就是最多划分的段数 \(k\),因为 \(k\) 段的方案可以选两个相邻的段合并得到 \(k-1\) 的方案。
把所有数减一,这样原题的最小缺失元素就是 \(\operatorname{MEX}\)。
考虑一个序列的 \(\operatorname{MEX}=x\),那么它划分出来的每个段 \(\operatorname{MEX}\le x\),进一步发现题目要求的每个段的 \(\operatorname{MEX}\) 就是 \(x\)。
证明考虑如果每个 \(\operatorname{MEX}=y\),那么合并起来整个序列 \(\operatorname{MEX}=y\),就跟我们一开始说 \(\operatorname{MEX}=x\) 矛盾了。
如果 \(q=1\),那么可以做一个暴力:从左往右扫,维护每个元素个数及其最后一次出现位置,并求出当前 \(\operatorname{MEX}\)。假设在位置 \(i\),\(\operatorname{MEX}=j\),\(<j\) 的元素最后一次出现位置的最小值是 \(k\),那我们就知道 \([k,i]\) 是一段 \(\operatorname{MEX}=j\) 的元素,而如果 \(j=x\),那么这就是一个对答案有贡献的段。
不过我们肯定不能碰到这样一个 \(j=x\) 就把答案加一,因为显然当某个 \(i\) 时有 \(j=x\),那么任意 \(i<i'\le r\) 都有 \(j=x\),而我们要的只是最多的段数。
所以答案的统计应该还要记录每个 \(i\) 对应的 \(k\),然后从右端点开始,每次从 \(i\) 跳到 \(k-1\),并把答案加一,直到 \(j\neq x\),这个贪心的正确性是显然的。
现在考虑多次询问,我们可以尝试把它丢到分治上,不过我们需要先解决怎样查询一个区间的 \(\operatorname{MEX}\),来找出每次询问的 \(x\)。
这个扫描线就好了,从左往右更新每个元素的最后出现位置,在右端点 \(r\) 查询最小的出现位置 \(<l\) 的元素,可以线段树二分解决。
然后考虑分治做上面那个暴力,我们从中点分别往左右跑一遍,求出每个位置 \(i\) 到中点的 \(\operatorname{MEX}\) 记做 \(val_i\),并记录能往前跳 \(k\) 的步数记做 \(step_i\),那么对于一个询问 \([l,r]\),如果 \(val_l=x\),那么其答案就加上 \(step_l\),\(r\) 同理。
不过这样就有个小问题是 \(l,r\) 两侧分别跳到底后可能还剩下一些元素,而这些元素因为被中点分开所以 \(\operatorname{MEX}\neq x\),但实际上可能形成一个对答案有贡献的段,因此我们记录步数的时候还要把剩余的区间记录下来,最后再求一下这些区间的 \(\operatorname{MEX}\)。
复杂度分析的话,每次分治需要花费 \(\operatorname{O}(L\lg L)\) 的时间处理,总共是 \(\operatorname{O}(N\lg^2N)\) 的。

浙公网安备 33010602011771号