Trick 记录:「极短 mex 区间」
Trick 记录:「极短 \(\operatorname {mex}\) 区间」
我觉得这个很有意思,所以决定记一下。
就是,做完找紫色数据结构做一下,然后翻到了 P10169。
给定序列 \(\{a_n\}\) 和 \(k\),求有多少子区间 \([l,r]\) 满足 \(\operatorname{mex}\{a_l,a_{l+1},\dots,a_{r-1},a_r\}+\min\{a_l,a_{l+1},\dots,a_{r-1},a_r\}+k\geq \max\{a_l,a_{l+1},\dots,a_{r-1},a_r\}\)。
\(\operatorname{mex}\) 定义为集合内没有出现过的最小的非负整数。
想了 0.67h 没想出来,推出了一些关键性质,但是还是不会单 \(\log\) 维护,遂看题解。
然后知道了一个很强大的性质:
- 定义「极短 \(\operatorname {mex}\) 区间」为满足如下性质的区间:设 \([l, r]\) 的区间 \(\operatorname{mex} = c\),\([l, r]\) 为「极短 \(\operatorname{mex}\) 区间」当且仅当不存在区间 \([l', r'] \subset [l, r]\) 满足 \([l', r']\) 的区间 \(\operatorname{mex} = c\)。
- 则对任意数列「极短 \(\operatorname{mex}\) 区间」的数量是 \(O(n)\) 级别的,具体地,有个上界 \(2n\)。
考虑证明。设 \([l, r]\) 是个极短区间。显然 \(a_l \not = a_r\)。不妨设 \(a_l > a_r\)。那么 \(a_r\) 和 \(a_l\) 的加入先后影响了这段区间的 \(\operatorname{mex}\)。把这两次操作撤销就能得到区间 \([l + 1, r]\) 的 \(\operatorname{mex} = a_l\) 并且 \([l + 1, r - 1]\) 的 \(\operatorname{mex} = a_r\)。而对于一个固定的 \(l + 1\),此时 \(a_l\) 已经固定。因为固定左端点时右端点向右移动区间 \(\operatorname{mex}\) 单调不降,所以对于每个 \(l\) 最多只有一个 \(r\) 满足条件。\(a_r > a_l\) 时同理。因此证明了极短区间的数量上界是 \(2n\)。
考虑找出所有的极短区间。
前置知识:主席树求区间 \(\operatorname{mex}\)。
但是我复习的时候肯定会重新看所以一句话描述一下:每个点维护当前权值最后出现的位置然后树上二分即可。
假设我们找到了 \(\operatorname{mex} = c\) 的极短区间,考虑推出 \(\operatorname{mex} = c + 1\) 的极短区间。
有个显然的结论是 \(\operatorname{mex} = x\) 的区间一定是由一个 \(\operatorname{mex} = y(y < x)\) 的区间加上 \(y\) 到 \(x\) 之间的数得到的。
维护一个 vector 作为极短区间候选。那么求出一个 \(c\) - 极短区间后,就从它的左端点和右端点分别向前和向后找到第一个 \(c + 1\),然后把这两段区间的 \(\operatorname{mex}\) 扔到对应的 vector 里作为候选即可。当我们枚举完了 \(1\) 到 \(c\) 的所有数,所有可能成为候选的区间一定都在 \(c+ 1\) 的候选 vector 里了。对这个 vector 求极短区间即可。
因为极短区间的数量是 \(O(n)\) 级别的,而每个区间只会提供 \(O(1)\) 个新的候选区间。所以任意时刻 vector 里的区间和的数量也是 \(O(n)\) 级别的。有个上界 \(4n\) 只是我不会证。
这样我们就在 \(O(n \log n)\) 的时间复杂度内得到了所有的极短区间。
再定义「极长 \(\operatorname{mex}\) 区间」,它表示的是所有满足不存在包含当前区间的与当前区间 \(\operatorname{mex}\) 相等的区间的区间。 有了极短区间后极长区间也很好求,将所有极短区间向左右找到第一个改变 \(\operatorname{mex}\) 的位置,就能得到极长区间。极长区间的数量级自然也是 \(O(n)\) 的。
考虑求出极短极长区间得到了什么。实际上,设 \([l, r]\) 是极短区间,\([L, R]\) 是对应的极长区间,则本质上得到的是 \(O(n)\) 个形如「若 \(l' \in [L, l], r' \in [r, R]\),则 \(\operatorname{mex}(l', r') = c\) 」这样的条件。把它扔到坐标系中,纵轴表示 \(l\) 横轴表示 \(r\),则我们将上三角那一片区域分成了 \(O(n)\) 个不交的矩形,每个区间的 \(\operatorname{mex}\) 就是它所在矩形的权值。这就能帮助我们做出很多题了。
P9970 [THUPC 2024 初赛] 套娃
我们定义一个集合的 \(\operatorname{mex}\) 是最小的不在 \(S\) 中的非负整数。
给定一个序列 \(a_1,\dots,a_n\),对于每个 \(1\leq k\leq n\),我们按照如下方式定义 \(b_k\):
- 对于 \(a\) 的所有长为 \(k\) 的子区间,求出这个子区间构成的数集的 \(\operatorname{mex}\)。
- 对于求出的所有 \(\operatorname{mex}\),求出这个数集自己的 \(\operatorname{mex}\),记为 \(b_k\)。
请你求出序列 \(b\)。
曾经和 SError_ 大蛇和 大眼仔Happy 大神打过的一场,但是当时没人去细想这个题。
根据上面的结论其实是很好做的。考虑每个长度对应的可重集。对于对应的 \(c\) - 极短极长区间 \([l, r], [L, R]\),它会给 \([r - l + 1, R - L + 1]\) 这段可重集中都提供一个 \(c\)。做差分并用 vector 记录每个集合开始的增删情况。
用 set 动态地维护当前未出现在集合中的数即可。由于可能会出现重复,因此可以选择用 multiset 或者开桶记录出现次数。
记录详情 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
P10169 [DTCPC 2024] mex,min,max
给定序列 \(\{a_n\}\) 和 \(k\),求有多少子区间 \([l,r]\) 满足 \(\operatorname{mex}\{a_l,a_{l+1},\dots,a_{r-1},a_r\}+\min\{a_l,a_{l+1},\dots,a_{r-1},a_r\}+k\geq \max\{a_l,a_{l+1},\dots,a_{r-1},a_r\}\)。
\(\operatorname{mex}\) 定义为集合内没有出现过的最小的非负整数。
这场好像我也打过,只是我还是没有去开这道题所以没印象了。
注意到 \(\operatorname{mex}\) 和 \(\min\) 必有一个为 \(0\),考虑容斥。
设 \(A\) 表示满足 \(\operatorname {mex} + k \ge \max\) 的区间个数,\(B\) 表示满足 \(\min + k \ge \max\) 的区间个数,\(C\) 表示 \(0 + k \ge \max\) 的区间个数,有最终答案为 \(A + B - C\)。\(B\) 和 \(C\) 是好求的。
考虑怎么求 \(A\)。仍然是考虑一组对应的 \(c\) - 极短极长区间 \([l, r], [L, R]\),那么此时 \(\operatorname{mex}\) 是固定的,则问题变成求有多少个区间满足 \(l' \in [L, l], r' \in [r, R], \max \le c + k\)。\(\max\) 是可重可并的,所以实际上我们只用在 \([L, l]\) 中找到最小的 \(cl\) 满足 \(\max \text {of }[cl, r] \le c + k\),然后在 \([r, R]\) 中找到 \(\max \text {of }[l, cr] \le c + k\) 的最大 \(cr\)。二分即可。这时对于所有 \(l' \in [cl, l], r' \in [r, cr]\) 的区间都满足条件。
这样的做法可以保证答案不漏,但无法保证不重。
发现每次形如钦定一个矩形合法,因此对所有矩形扫描线求面积并即可。
码量还是挺大的,但是很好调,至少我一写完代码就直接过样例了,改了下 RE 和 MLE 就过了(