BZOJ 3585: mex

3585: mex

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 778  Solved: 416
[Submit][Status][Discuss]

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

[Submit][Status][Discuss]

 

先处理出以1为左区间,i为右区间的所有mex值,发现是单调的。然后离线询问,按照左端点排序。如果当前询问和mex的左区间一样,直接取出答案,否则去掉左区间的数字,更新mex数组。更新时倒着更新就可以了。

 

 1 #include <bits/stdc++.h>
 2 
 3 const int mxn = 200005;
 4 
 5 int n, m, num[mxn], nxt[mxn], lst[mxn], mex[mxn], vis[mxn], ans[mxn];
 6 
 7 struct query {
 8     int l, r, t;
 9 }q[mxn];
10 
11 inline bool cmp(const query &a, const query &b)
12 {
13     return a.l < b.l;
14 }
15 
16 signed main(void)
17 {
18     scanf("%d%d", &n, &m);
19     
20     for (int i = 1; i <= n; ++i)
21     {
22         scanf("%d", num + i);
23         if (num[i] > n)
24             num[i] = n;
25     }
26     
27     for (int i = 0; i <= n; ++i)
28         lst[i] = n + 1;
29     
30     for (int i = n; i >= 1; --i)
31         nxt[i] = lst[num[i]], lst[num[i]] = i;
32         
33     for (int i = 1; i <= n; ++i)
34     {
35         mex[i] = mex[i - 1];
36         vis[num[i]] = true;
37         while (vis[mex[i]])
38             ++mex[i];
39     }
40     
41     for (int i = 1; i <= m; ++i)
42         scanf("%d%d", &q[i].l, &q[i].r), q[i].t = i;
43     
44     std::sort(q + 1, q + m + 1, cmp);
45     
46     int left = 1;
47     
48     for (int i = 1; i <= m; ++i)
49     {
50         while (left < q[i].l)
51         {
52             int t = nxt[left];
53             int p = num[left];
54             for (int j = t - 1; j > left; --j)
55             {
56                 if (mex[j] <= p)break;
57                 else mex[j] = p;
58             }
59             ++left;
60         }
61         
62         ans[q[i].t] = mex[q[i].r];
63     }
64     
65     for (int i = 1; i <= m; ++i)
66         printf("%d\n", ans[i]);
67 }

 

@Author: YouSiki

 

posted @ 2017-01-11 11:30  YouSiki  阅读(289)  评论(0编辑  收藏  举报