实际这题只需要考虑<=n的值
区间mex有两个经典做法,一个是莫队+对权值分块,另一个就是主席树
我们对1~i建立主席树,位置j维护1~i中,j最后一次出现的位置
查询
l r
l
r
时,在第
r
r
棵主席树上找到第一个的值
O(nlogn)
O
(
n
l
o
g
n
)
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define pb push_back
using namespace std;
const int maxn = 410000;
int n,m,u;
int c[maxn];
struct node
{
int x;
int *i;
friend inline bool operator <(const node x,const node y){return x.x<y.x;}
}a[maxn]; int To[maxn];
void Trans()
{
for(int i=1;i<=n;i++) a[i].x=c[i],a[i].i=&c[i];
sort(a+1,a+n+1);
To[u=1]=a[0].x=0;
for(int i=1;i<=n;i++)
{
if(a[i].x==a[i-1].x+1) To[++u]=a[i].x;
else if(a[i].x>a[i-1].x+1)
{
To[++u]=a[i-1].x+1;
To[++u]=a[i].x;
}
(*a[i].i)=u;
}
To[++u]=a[n].x+1;
}
struct Segment
{
int seg[maxn<<2];
int loc,c;
void pushup(int x){ seg[x]=min(seg[x<<1],seg[x<<1|1]); }
void upd(const int x,const int l,const int r)
{
if(l==r) { seg[x]=c;return; }
int mid=l+r>>1;
if(loc<=mid) upd(x<<1,l,mid);
else upd(x<<1|1,mid+1,r);
pushup(x);
}
int query(int x,const int l,const int r)
{
if(l==r) return l;
int mid=l+r>>1;
return seg[x<<1]>=c?query(x<<1|1,mid+1,r):query(x<<1,l,mid);
}
}Seg;
int op[maxn][2];
vector<int>V[maxn];
int ans[maxn];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&c[i]);
Trans();
for(int i=1;i<=m;i++)
{
scanf("%d%d",&op[i][0],&op[i][1]);
V[op[i][1]].pb(i);
}
for(int i=1;i<=n;i++)
{
Seg.loc=c[i],Seg.c=i,Seg.upd(1,1,u);
for(int j=0;j<(int)V[i].size();j++)
{
int qi=V[i][j];
Seg.c=op[qi][0];
ans[qi]=Seg.query(1,1,u);
}
}
for(int i=1;i<=m;i++) printf("%d\n",To[ans[i]]);
return 0;
}