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

Sample Output

1
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 }
分块&莫队

相关文章: