AlenaNuna

导航

分块+莫队||BZOJ3339||BZOJ3585||Luogu4137||Rmq Problem / mex

题面:P4137 Rmq Problem / mex

题解:先莫队排序一波,然后对权值进行分块,找出第一个没有填满的块,直接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

posted on 2018-12-23 12:14  AlenaNuna  阅读(130)  评论(0编辑  收藏  举报