P9970 [THUPC 2024 初赛] 套娃

题面

定义一个集合的 mex 是最小的不在 S 中的非负整数。给定一个序列 a1,,an,对于每个 1kn,我们按照如下方式定义 bk

  • 对于 a 的所有长为 k 的子区间,求出这个子区间构成的数集的 mex
  • 对于求出的所有 mex,求出这个数集自己的 mex,记为 bk

请你求出序列 b

数据范围:1n105,ain

题解

感觉挺难的啊,为毛过了一车人...

总体的思路是找到形如 [l1,r1][l2,r2] 这样的区间,使 l[l1,r1],r[l2,r2],mex(alar)=t ,那么我们就可以对 kl2r1+1r2l1+1 的这些 bk 都加上 t 元素,将这些修改操作扫描线处理一下,然后就可以用线段树上二分的方式找最小的没有出现的元素。

现在考虑去求这样的区间。

首先是一个结论:记最小 mex 区间表示:对于一个区间 [l,r],不存在一个子区间 [l1,r1],使 mex(alar)=mex(al1ar1) ,那么一个序列的所有最小 mex 区间的数量是 O(n) 的。

证明:对于一个满足条件的最小的 mex 区间 [l,r], 显然满足 alar,否则删任意一个不影响答案。不妨假设 al>ar,那么有 mex(alar)al>ar

此时如果还存在一个 r1 使得 r1>ral>ar1 ,那么 ar1 一定在 alar 中出现过了(不然 mex(alar) 不会大于等于 al),那么对于一个 ai 来说,那些比他 aj 大,并且和 i 组成最小 mex区间的 j 只会出现最多 2 次,那么整个序列最多就是 2n 个最小 mex 序列。

现在我们考虑维护所有的最小 mex 区间 (l,r,k),k=mex(alar),考虑往其两边扩展,那么就是找到 l 左边和 r 右边最近的 t 使 at=k ,求出其 mex,那么就可以找到所有可能的最小 mex 区间。

注意并不是一定,如 2,1,0,1,0,那么 (4,5,2) 往左扩展会到 (1,5,3) ,很明显不是最小 mex 区间。

对于一组最小 mex 区间,求出其最大 mex 区间是比较显然的,左右端点就是 l 左边和 r 右边最近的 k ,在计算扩展区间的时候就已经处理出来了。

那么我们整个算法流程就是:

  • 预处理出极小的 (,,0)(,,1) 的区间。
  • 对于每一个 (l,r,x) 区间,分别求出其距离左端点最近的 x 出现位置 l1,和距离右端点最近的 x1 出现位置 r1,形成两个新的区间,算一下 (l1,r),(l,r1)mex,然后丢到对应的存储 (,,x) 区间的 vector 里,并且将 [l1+1,l],[r,r11],x 记录下来后续处理。
  • 对于每一个 x ,先将删去被包含的区间,在对每一个 (,,x) 进行扩展。

注意这里要有一个在线求 [l,r] 的算法,就是 P4137 。考虑建立一个主席树,每一个节点 [l,r] 存的是 (alar) 中最晚出现的下表,这样在查询 l,r 的时候我们就在 r 那一棵树上找出现时间 <l 的最小的节点是什么。

启发

  • 关于 mex 的一个结论:一个序列的所有最小 mex 区间的数量是 O(n) 的。
  • 关于求区间 mex 的算法:主席树+线段树二分。

本文作者:qwq_123

本文链接:https://www.cnblogs.com/qwq-123/p/17935194.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   qwq_123  阅读(78)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起