[CF407E]k-d-sequence
远古题,评分 *3100 有点虚高了。
Description
给定 \(k,d\) 和序列 \(\{a_n\}\),求一个最长子区间 \(a[l:r]\) 满足:
- \(a[l:r]\) 中的每个数和 \(k\) 个任意整数共 \(r-l+1+k\) 个数排序后形成一个公差为 \(d\) 的等差数列。
\(n,k \le 10^5\),\(d,a_i\le10^9\)
Solution
先特判掉 \(d=0\) 的情形,这种情况就是求最长同颜色子段。
若 \(a[l:r]\) 满足要求,一个显然的必要条件是 \(a[l:r]\) 中的数在\(\pmod d\) 意义下相同。
在本题中,由于还有 \(k\) 个数可以随意选,所以还有一个必要条件是 \(\max\{a[l:r]\}-\min\{a[l:r]\} \leq d(r-l+k)\)。另外 \(a[l:r]\) 不能存在相同的元素。
满足上面 \(3\) 个条件后,可以证明一定满足题目要求。
整理思路,就是求满足
\(\mathrm{max} -\mathrm{min} \le d(r-l+k) \land \forall l\le i<j\le r:a_i\neq a_j\)
的最长 \(a[l:r]\)。
共两个条件,一个一个考虑。
-
第一个条件转换一下,变成 \(\mathrm{max}-\mathrm{min}-l \cdot d\le d(r+k)\),这样将 \(r\) 从 \(1\) 扫到 \(n\) 时,对于每个 \(r\),\(d(r+k)\) 是定值,方便讨论左侧的值以后用数据结构找 \(l\)。现在期望能在我们在扫到 \(r\) 时,对于每个 \(l\) 左侧值都能正确维护。
考虑线段树,鉴于其不好维护 \(\mathrm{max},\mathrm{min}\) 的变化,使用单调栈辅助维护。由于单调栈的每一个元素 \(i\) 有一个管辖区间,对于它自己的管辖区间 \([L_i,i]\) 来说,\(\forall j \in [L_i,i]\),\(j \sim r\) 的最值都是它,这样在弹栈时删去的元素的管辖区间交给新加入的元素管理,在线段树上就是一个区间加/减的操作,非常方便。
-
第二个条件限定了 \(l\) 的下限,对每个元素维护前一个相同值 \(pre_i\) 即可。
这个单调栈辅助维护 \(\max,\min\) 的 trick 很常见?
详见:CF526F(洛谷链接)

浙公网安备 33010602011771号