【bzoj3585】mex 线段树 mex,sg
Description
有一个长度为n的数组{a1,a2,…,an}。m次询问,每次询问一个区间内最小没有出现过的自然数。
Input
第一行n,m。
第二行为n个数。
从第三行开始,每行一个询问l,r。
Output
一行一个数,表示每个询问的答案。
Sample Input
5 5
2 1 0 2 1
3 3
2 3
2 4
1 2
3 5
2 1 0 2 1
3 3
2 3
2 4
1 2
3 5
Sample Output
1
2
3
0
3
2
3
0
3
HINT
数据规模和约定
对于100%的数据:
1<=n,m<=200000
0<=ai<=109
1<=l<=r<=n
对于30%的数据:
1<=n,m<=1000
离线瞎XX乱搞,只需要先处理出前缀的sg,表示最小没出现的自然数,然后就是
根据影响范围搞线段树即可
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 7 #define inf 0x7fffffff 8 using namespace std; 9 inline int read() 10 { 11 int x=0;char ch=getchar(); 12 while(ch<'0'||ch>'9'){ch=getchar();} 13 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 14 return x; 15 } 16 17 int n,m,cnt,k=0; 18 int a[200005],b[200005],sg[200005],ans[200005],next[200005],last[200005]; 19 int ls[600005],rs[600005],mn[600005]; 20 bool mark[200005]; 21 22 struct data{int l,r,id;}q[200005]; 23 bool cmp(data a,data b) 24 {return a.l<b.l;} 25 int find(int x) 26 { 27 int l=1,r=cnt; 28 while(l<=r) 29 { 30 int mid=(l+r)>>1; 31 if(b[mid]<x)l=mid+1; 32 else r=mid-1; 33 } 34 return l; 35 } 36 void build(int k,int l,int r) 37 { 38 ls[k]=l;rs[k]=r;mn[k]=inf; 39 if(l==r){mn[k]=sg[l];return;} 40 int mid=(l+r)>>1; 41 build(k<<1,l,mid);build(k<<1|1,mid+1,r); 42 } 43 void pushdown(int k) 44 { 45 int l=ls[k],r=rs[k]; 46 if(l==r)return; 47 mn[k<<1]=min(mn[k],mn[k<<1]); 48 mn[k<<1|1]=min(mn[k],mn[k<<1|1]); 49 } 50 int ask(int k,int x) 51 { 52 if(mn[k]!=inf)pushdown(k); 53 int l=ls[k],r=rs[k]; 54 if(l==r)return mn[k]; 55 int mid=(l+r)>>1; 56 if(x<=mid)return ask(k<<1,x); 57 return ask(k<<1|1,x); 58 } 59 void update(int k,int x,int y,int val) 60 { 61 if(mn[k]!=inf)pushdown(k); 62 int l=ls[k],r=rs[k]; 63 if(l==x&&y==r){mn[k]=min(mn[k],val);return;} 64 int mid=(l+r)>>1; 65 if(y<=mid)update(k<<1,x,y,val); 66 else if(x>mid)update(k<<1|1,x,y,val); 67 else {update(k<<1,x,mid,val);update(k<<1|1,mid+1,y,val);} 68 } 69 int main() 70 { 71 n=read(),m=read(); 72 for(int i=1;i<=n;i++) 73 a[i]=b[i]=read(); 74 sort(b+1,b+n+1); 75 for(int i=1;i<=n;i++) 76 if(b[i]!=b[i-1]||i==1)b[++cnt]=b[i]; 77 for(int i=1;i<=n;i++) 78 { 79 int t=find(a[i]); 80 mark[t]=1; 81 if(a[i]==k) 82 while(mark[t]) 83 { 84 k++; 85 if(b[++t]!=k)break; 86 } 87 sg[i]=k; 88 } 89 build(1,1,n); 90 for(int i=n;i>0;i--) 91 next[i]=last[find(a[i])],last[find(a[i])]=i; 92 /*for (int i=1;i<=n;i++) 93 cout<<next[i]<<" "; 94 cout<<endl; 95 for (int i=1;i<=n;i++) 96 cout<<last[i]<<" "; 97 cout<<endl;*/ 98 for(int i=1;i<=m;i++) 99 { 100 q[i].l=read();q[i].r=read(); 101 q[i].id=i; 102 } 103 sort(q+1,q+m+1,cmp); 104 int now=1; 105 for(int i=1;i<=m;i++) 106 { 107 while(now<q[i].l) 108 { 109 if(!next[now])next[now]=n+1; 110 update(1,now,next[now]-1,a[now]); 111 now++; 112 } 113 ans[q[i].id]=ask(1,q[i].r); 114 } 115 for(int i=1;i<=m;i++) 116 printf("%d\n",ans[i]); 117 }