分析:
我们转化一下,离线,把直接求区间mex转化成先求以1为左端点的区间mex…
我们考虑区间[l,r]的mex和[l+1,r]的mex有什么变化…这些区间的数字少了a[l],如果区间[l,r]的mex大于a[l],那么显然去掉a[l]之后区间[l+1,r]的mex就变成了a[l]…
所以我们按照左端点排序…首先预处理出来所有的[1,r]的mex,然后每次减少一个数字(起点往后加1)就把当前数字的下一次出现位置到当前位置的mex函数全部和当前的左端点取min…
但是如果暴力修改会挂的很惨…还不如写个暴力…
所以说我们考虑mex的性质…
左端点相同的mex是单调不降的…
所以我们可以用线段树来更新mex函数…
代码如下:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
//by NeighThorn
#define inf 5000000
using namespace std;
const int maxn=200000+5;
int n,q,a[maxn],mex[maxn],nxt[maxn],last[maxn],vis[maxn];
struct M{
int l,r,id,ans;
}s[maxn];
struct Tree{
int l,r,lazy;
}tree[maxn*4];
inline bool cmp1(M a,M b){
return a.l<b.l;
}
inline bool cmp2(M a,M b){
return a.id<b.id;
}
inline void build(int l,int r,int tr){
tree[tr].l=l;tree[tr].r=r;tree[tr].lazy=inf;
if(l==r){
tree[tr].lazy=mex[l];
return;
}
int mid=(l+r)>>1;
build(l,mid,tr<<1),build(mid+1,r,tr<<1|1);
}
inline void change(int l,int r,int val,int tr){
if(tree[tr].l==l&&tree[tr].r==r){
tree[tr].lazy=min(tree[tr].lazy,val);
return;
}
if(tree[tr].lazy!=inf&&tree[tr].l!=tree[tr].r){
tree[tr<<1].lazy=min(tree[tr<<1].lazy,tree[tr].lazy);
tree[tr<<1|1].lazy=min(tree[tr<<1|1].lazy,tree[tr].lazy);
}
int mid=(tree[tr].l+tree[tr].r)>>1;
if(r<=mid)
change(l,r,val,tr<<1);
else if(l>mid)
change(l,r,val,tr<<1|1);
else
change(l,mid,val,tr<<1),change(mid+1,r,val,tr<<1|1);
}
inline int query(int x,int tr){
if(tree[tr].l==tree[tr].r)
return min(tree[tr].lazy,mex[x]);
if(tree[tr].lazy!=inf&&tree[tr].l!=tree[tr].r){
tree[tr<<1].lazy=min(tree[tr<<1].lazy,tree[tr].lazy);
tree[tr<<1|1].lazy=min(tree[tr<<1|1].lazy,tree[tr].lazy);
}
int mid=(tree[tr].l+tree[tr].r)>>1;
if(x<=mid)
return query(x,tr<<1);
else
return query(x,tr<<1|1);
}
signed main(void){
scanf("%d%d",&n,&q);
memset(last,0,sizeof(last));
for(int i=1;i<=n;i++)
nxt[i]=n+1;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
if(last[a[i]])
nxt[last[a[i]]]=i,last[a[i]]=i;
else
last[a[i]]=i;
}int lala=0;
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++){
if(a[i]==lala){
vis[a[i]]=1;
while(vis[lala])
lala++;
}
else
vis[a[i]]=1;
mex[i]=lala;
}build(1,n,1);
for(int i=1;i<=q;i++)
scanf("%d%d",&s[i].l,&s[i].r),s[i].id=i;
sort(s+1,s+q+1,cmp1);lala=1;
for(int i=1;i<=n;i++){
while(s[lala].l==i)
s[lala].ans=query(s[lala].r,1),lala++;
change(i,nxt[i]-1,a[i],1);
}
sort(s+1,s+q+1,cmp2);
for(int i=1;i<=q;i++)
printf("%d\n",s[i].ans);
return 0;
}
by >_< NeighThorn