快来踩爆这个蒟蒻吧|

Little_corn

园龄:1年1个月粉丝:11关注:17

2025-02-18 22:15阅读: 18评论: 0推荐: 0

关于 mex

最近偶遇一堆 mex 题,记一些常见结论。

  • 求区间 mex

首先有一个不好的莫队文明,点名批评一下,拓展性不好且难写且离线且跑的巨慢。

下面有两个求法:

  1. 可持久化值域线段树

其实就是主席树求法啦,但是为了区分做法 2,强调值域。首先考虑转化问题,一个数 x 在区间 [l,r] 中出现当且仅当 lstr,xl。建出值域线段树并可持久化来维护 lst 数组,于是求 mex 相当于在线段树上二分。码量很小。

例题:P9970 [THUPC 2024 初赛] 套娃

qwq
#define mid (l + r >> 1)
struct node{
int ls, rs, lst;
}hjt[N << 5];
int cnt, root[N];
void pushup(int o){hjt[o].lst = min(hjt[hjt[o].ls].lst, hjt[hjt[o].rs].lst);}
void add(int pre, int& o, int l, int r, int x, int k){
hjt[++cnt] = hjt[pre]; o = cnt;
if(l == r){hjt[o].lst = k; return;}
if(x <= mid) add(hjt[pre].ls, hjt[o].ls, l, mid, x, k);
else add(hjt[pre].rs, hjt[o].rs, mid + 1, r, x, k);
pushup(o);
}
int qrymin(int o, int l, int r, int pivot){
if(l == r) return l;
if(hjt[hjt[o].ls].lst < pivot) return qrymin(hjt[o].ls, l, mid, pivot);
else return qrymin(hjt[o].rs, mid + 1, r, pivot);
}
  1. 颜色段均摊 + 可持久化线段树

这个做法非常具有拓展性和启发性。

不妨考虑扫描线,每次把右端点 r 向右移动一段,然后使用线段树维护 l=1r[l,r] 的答案。不难发现 mex 具有单调性,且有很多连续段。考虑颜色段均摊,将 mex 相同的区间看作一个颜色段,每次加入 x=ar 就在线段树上二分找到 [lx,rx] 这个 mex=x 的颜色段,然后把这个颜色段 +1。 接着找到最右位置小于等于 rx 最右的出现位置 p,将颜色段分裂为 [lx,p],[p+1,r] 两个区间。然后把左边的区间 mex 更新,不断重复这个过程,直到某个数没有出现。

但是时间复杂度呢?实际上这个取决于分裂的次数,相当于新建段或者和合并段的次数。注意到,每次加入一个数,只有可能使得 [lx,rx] 分裂出来最左边的段和前面最右的段合并,即总共只会合并 O(n) 次。最多新建段的个数也是 O(n) 的。于是时间复杂度 O(nlogn),将线段树可持久化就可以实现在线回答询问。

例题:CF1148H Holy Diver

  • 极小 mex 区间

我们定义一个区间 [l,r] 是极小 mex 区间,当 mex(l,r)mex(l+1,r),mex(l,r)mex(l,r1)

接下来证明这样的区间只会有 O(n) 个。

不妨考虑固定左端点 l,寻找符合条件的 r,那么不难发现,需要满足 mex(l+1,r)=al,由于固定 l 时是单调不降的,那么满足条件的我们取最左边的一个即可。固定右端点也是一样的。因此严格上界是 2n 个。

构造方法很简单,不再写了。

例题:套娃

本文作者:little-corn

本文链接:https://www.cnblogs.com/little-corn/p/18722880

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

posted @   Little_corn  阅读(18)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起