题解:先莫队排序一波,然后对权值进行分块,找出第一个没有填满的块,直接for一遍找答案。
除了bzoj3339以外,另外两道题Ai范围都是1e9。显然最劣情况下答案是N,所以大于N的Ai都直接无视就可以。
由于求的是最小的自然数,自然数包括0,所以要额外处理一下含有0的块。我这里是直接把0拖出来放在第0块了。
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 inline int rd(){ 8 int f=1,x=0;char c=getchar(); 9 while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();} 10 while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();} 11 return f*x; 12 } 13 const int maxn=200005,maxm=200005,max_block=500; 14 int N,M,A[maxn],l,r,block,Ans[maxm],vis[maxn],cnt[max_block],num,belong[maxn]; 15 struct Q{ 16 int id,l,r; 17 }q[maxm]; 18 inline bool cmp(const Q&a,const Q&b){ 19 if(belong[a.l]==belong[b.l])return a.r<b.r; 20 return a.l<b.l; 21 } 22 inline void Add(int x){ 23 if(x<=N){ 24 if(vis[x]==0)cnt[belong[x]]++; 25 vis[x]++; 26 } 27 return; 28 } 29 inline void Del(int x){ 30 if(x<=N){ 31 vis[x]--; 32 if(vis[x]==0)cnt[belong[x]]--; 33 } 34 return; 35 } 36 int main(){ 37 N=rd();M=rd(); 38 block=sqrt(N); 39 num=N/block; 40 if(N%block)num++; 41 for(int i=1;i<=N;i++){ 42 A[i]=rd(); 43 belong[i]=(i-1)/block+1; 44 } 45 belong[0]=0; 46 for(int i=1;i<=M;i++){ 47 q[i].id=i; 48 q[i].l=rd(); 49 q[i].r=rd(); 50 } 51 sort(q+1,q+M+1,cmp); 52 l=1;r=0; 53 for(int i=1;i<=M;i++){ 54 int ql=q[i].l,qr=q[i].r,id=q[i].id; 55 while(l<ql)Del(A[l++]); 56 while(l>ql)Add(A[--l]); 57 while(r<qr)Add(A[++r]); 58 while(r>qr)Del(A[r--]); 59 if(cnt[0]==0){ 60 Ans[id]=0; 61 continue; 62 } 63 int t=-1; 64 for(int j=1;j<=num;j++){ 65 if(j!=num&&cnt[j]!=block){ 66 t=j; 67 break; 68 } 69 else if(cnt[j]!=N-(num-1)*block) t=j; 70 } 71 if(t==-1){ 72 Ans[id]=N; 73 continue; 74 } 75 int f=(t-1)*block+1,toj=t*block; 76 for(int j=f;j<=toj;j++) 77 if(vis[j]==0){ 78 Ans[id]=j; 79 break; 80 } 81 } 82 for(int i=1;i<=M;i++)printf("%d\n",Ans[i]); 83 return 0; 84 }
By:AlenaNuna