loading...

[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(洛谷链接)

posted @ 2025-02-13 11:37  goldspade  阅读(12)  评论(0)    收藏  举报