3339: Rmq Problem
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1237 Solved: 646
[ Submit][ Status][ Discuss]
Description
Input
Output
Sample Input
7 5
0 2 1 0 1 3 2
1 3
2 3
1 4
3 6
2 7
0 2 1 0 1 3 2
1 3
2 3
1 4
3 6
2 7
Sample Output
3
0
3
2
4
0
3
2
4
HINT
/*
1 到i(1<=i<=n)的mex可以线性求出来.
考虑l到r和l+1 到r 的答案有何不同.
令next[l] 表.A[L] 下次出现的位置.
显然是l 到next[l]-1 这段所有sg 值大于于a[l] 的变为a[l]
然后线段树维护一下就可以了.
*/
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define MAXN 200010
#define INF 0x7fffffff
struct Question{ int l,r,order,ans; }query[MAXN];
bool cmp1(Question a,Question b){ return a.l<b.l; }
bool cmp2(Question a,Question b){ return a.order<b.order; }
struct Seg_Tree{int l,r,mn,tag;}tre[MAXN<<3];
int n,q,mex[MAXN],a[MAXN],last[MAXN],next[MAXN],c[MAXN];
void Build(int u,int l,int r){
tre[u].l=l;tre[u].r=r;tre[u].tag=INF;
if(l==r){ tre[u].mn=mex[l];return; }
int Mid=(l+r)>>1;
Build(u<<1,l,Mid);
Build(u<<1|1,Mid+1,r);
}
void Modify(int u,int l,int r,int c){
if(l<=tre[u].l&&tre[u].r<=r){
tre[u].tag=min(tre[u].tag,c);
tre[u].mn=min(tre[u].mn,c);
return ;
}
int mid=(tre[u].l+tre[u].r)>>1;
if(l<=mid) Modify(u<<1,l,r,c);
if(mid<r) Modify(u<<1|1,l,r,c);
}
int getmn(int u,int pos){
if(tre[u].l==tre[u].r) return tre[u].mn;
int mid=(tre[u].l+tre[u].r)>>1,ret=tre[u].tag;
if(pos<=mid) return min(ret,getmn(u<<1,pos));
else return min(tre[u].tag,getmn(u<<1|1,pos));
}
int main(){
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=q;i++){
scanf("%d%d",&query[i].l,&query[i].r);
query[i].order=i;
}
sort(query+1,query+1+q,cmp1);
for(int i=n;i>=1;i--){
next[i]=last[a[i]];
if(next[i]==0) next[i]=n+1;
last[a[i]]=i;
}
int now=0;
for(int i=1;i<=n;i++){
c[a[i]]=1;
while(c[now]) now++;
mex[i]=now;
}
Build(1,1,n);
query[0].l=1;
for(int i=1;i<=q;i++){
int prel=query[i-1].l,l=query[i].l;
for(int j=prel;j<l;j++) Modify(1,j+1,next[j]-1,a[j]);
query[i].ans=getmn(1,query[i].r);
}
sort(query+1,query+1+q,cmp2);
for(int i=1;i<=q;i++) printf("%d\n",query[i].ans);
return 0;
}