• 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
    ", ans[i]);
    67 }

    @Author: YouSiki

  • 相关阅读:
    屏幕适配的简单介绍
    静态单元格
    BOOL的getter方法
    取消注册监听器
    自定义cell
    假适配
    cell的重用
    UITableView的简单使用
    UISrcoll控件简单介绍
    创建ios界面的三步骤
  • 原文地址:https://www.cnblogs.com/yousiki/p/6272923.html
Copyright © 2020-2023  润新知