Rmq Problem mex

求区间mex。莫队可做。

但如果强制在线,就可以用主席树做。

建立权值线段树,找每个数最后一次出现的位置。查询的时候找第r棵线段树最近出现位置在l之前的最小数即可。update的时候可以update这个数和这个数+1,如果没有这个数+1,那ans就是这个数+1.(好乱啊,看代码吧

// luogu-judger-enable-o2
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
int n,m;
const int N=4e5+7;
int rt[N],ls[N<<5],rs[N<<5],last[N<<5],tot,lsh[N],LSH=1,a[N];
#define mid (l+r>>1)
void build(int &k,int l,int r) {k=++tot;if(l<r) build(ls[k],l,mid),build(rs[k],mid+1,r);}
void update(int &k,int pre,int l,int r,int pos,int lst) {
    ls[k=++tot]=ls[pre],rs[k]=rs[pre];last[k]=last[pre];
    if(l==r) {last[k]=lst;return;}
    if(pos<=mid) update(ls[k],ls[pre],l,mid,pos,lst);
    else update(rs[k],rs[pre],mid+1,r,pos,lst);
    last[k]=min(last[ls[k]],last[rs[k]]);
}
int query(int k,int l,int r,int c) {
    if(!k||l==r) return lsh[l];
    if(last[ls[k]]>=c) return query(rs[k],mid+1,r,c);
    return query(ls[k],l,mid,c);
}
#undef mid
int main() {
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),lsh[++LSH]=a[i],lsh[++LSH]=a[i]+1;
    sort(lsh+1,lsh+1+LSH);LSH=unique(lsh+1,lsh+1+LSH)-lsh-1;
    build(rt[0],1,LSH);
    for(int i=1;i<=n;i++) a[i]=lower_bound(lsh+1,lsh+1+LSH,a[i])-lsh,update(rt[i],rt[i-1],1,LSH,a[i],i);
    for(int i=1,l,r;i<=m;i++) {
        scanf("%d%d",&l,&r);
        printf("%d
",query(rt[r],1,LSH,l));
    }
    return 0;
}
我是咸鱼。转载博客请征得博主同意Orz
原文地址:https://www.cnblogs.com/sdfzhsz/p/9537818.html