P4137 Rmq Problem / mex

P4137 Rmq Problem / mex

主席树的大水题
维护每个自然数前一个出现的位置
关于查询\(l,r\)区间,在第\(r\)颗主席树查询位置小于\(l\)的第一个数

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
typedef long long LL;
const LL maxn=1e7+10;
inline LL Read(){
    LL x=0,f=1; char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-') f=-1; c=getchar();
    }
    while(c>='0'&&c<='9')
        x=(x<<3)+(x<<1)+c-'0',c=getchar();
    return x*f;
}
LL n,m,nod;
LL d_min[maxn],son[maxn][2],a[maxn],root[maxn];
inline void Update(LL now){
    LL l=son[now][0],r=son[now][1];
    d_min[now]=min(d_min[l],d_min[r]);
}
void Change(LL &now,LL pre,LL l,LL r,LL c,LL val){
    now=++nod;
    if(l==r){
        d_min[now]=val;
        return;
    }
    LL mid=(l+r)>>1;
    if(c<=mid){
        Change(son[now][0],son[pre][0],l,mid,c,val);
        son[now][1]=son[pre][1];
    }else{
        Change(son[now][1],son[pre][1],mid+1,r,c,val);
        son[now][0]=son[pre][0];
    }
    Update(now);
}
LL Query(LL now,LL c,LL l,LL r){
    if(l==r)
        return l;
    LL mid=(l+r)>>1;
    if(d_min[son[now][0]]<c)
        return Query(son[now][0],c,l,mid);
    else
        return Query(son[now][1],c,mid+1,r);
}
int main(){
    n=Read(),m=Read();
    for(LL i=1;i<=n;++i)
        a[i]=Read();
    for(LL i=1;i<=n;++i){
        if(a[i]<=n)
            Change(root[i],root[i-1],0,n,a[i],i);
        else
            root[i]=root[i-1];
    }
    while(m--){
        LL l=Read(),r=Read();
        printf("%lld\n",Query(root[r],l,0,n));
    }
    return 0;
}/*
*/
posted @ 2018-12-28 16:19  y2823774827y  阅读(110)  评论(0编辑  收藏  举报