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
Source
题目大意
区间询问mex。
Solution 1 Mo's Algorithm & Block Division
区间求mex?不会,直接莫队。
由于一个数大于等于$n$时无意义,所以按$n$分块,每块记录是否完全被覆盖。
查询时暴力跳。
表示数据真水,最开始某个地方的$x$,写成$p$竟然A了。
Code
1 /** 2 * bzoj 3 * Problem#3585 4 * Accepted 5 * Time: 6832ms 6 * Memory: 5988k 7 */ 8 #include <bits/stdc++.h> 9 using namespace std; 10 typedef bool boolean; 11 12 const int cs = 500; 13 14 typedef class Query { 15 public: 16 int l, r; 17 int id; 18 19 Query() { } 20 21 boolean operator < (Query b) const { 22 if (l / cs != b.l / cs) return l < b.l; 23 return r < b.r; 24 } 25 }Query; 26 27 int n, m; 28 int* ar; 29 Query* qs; 30 int exist[200005]; 31 int cover[cs]; 32 int *res; 33 34 inline void init() { 35 scanf("%d%d", &n, &m); 36 ar = new int[(n + 1)]; 37 qs = new Query[(m + 1)]; 38 res = new int[(m + 1)]; 39 for (int i = 1; i <= n; i++) 40 scanf("%d", ar + i); 41 for (int i = 1; i <= m; i++) 42 scanf("%d%d", &qs[i].l, &qs[i].r), qs[i].id = i; 43 } 44 45 inline void update(int p, int sign) { 46 int x = ar[p]; 47 if (x >= n) return; 48 if (!exist[x] && sign == 1) cover[x / cs]++; 49 exist[x] += sign; 50 if (!exist[x] && sign == -1)cover[x / cs]--; 51 } 52 53 inline void solve() { 54 sort(qs + 1, qs + m + 1); 55 int mdzzl = 1, mdzzr = 0; 56 for (int i = 1; i <= m; i++) { 57 while (mdzzr < qs[i].r) update(++mdzzr, 1); 58 while (mdzzr > qs[i].r) update(mdzzr--, -1); 59 while (mdzzl < qs[i].l) update(mdzzl++, -1); 60 while (mdzzl > qs[i].l) update(--mdzzl, 1); 61 62 for (int j = 0; j < cs; j++) { 63 if (cover[j] < cs) { 64 int k = j * cs; 65 while (exist[k]) k++; 66 res[qs[i].id] = k; 67 break; 68 } 69 } 70 } 71 72 for (int i = 1; i <= m; i++) 73 printf("%d\n", res[i]); 74 } 75 76 int main() { 77 init(); 78 solve(); 79 return 0; 80 }