BZOJ 3339: Rmq Problem

来源:互联网 发布:gif快手刷粉丝软件 编辑:程序博客网 时间:2024/05/04 14:06


3339: Rmq Problem

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 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

Sample Output

3
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 0x7fffffffstruct 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;}