zoukankan      html  css  js  c++  java
  • 【线段树】bzoj3585: mex

    非常精妙的线段树题

    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


    题目分析

    细节很精妙

      1 #include<bits/stdc++.h>
      2 const int maxn = 200035;
      3 const int INF = 2e9;
      4 
      5 struct QRs
      6 {
      7     int l,r,id;
      8     bool operator < (QRs a) const
      9     {
     10         return l < a.l||(l==a.l&&r < a.r);
     11     }
     12 }q[maxn];
     13 int n,m,tt,now;
     14 int a[maxn],b[maxn],mn[maxn<<2];
     15 int hsh[maxn],sgVal[maxn],ans[maxn];
     16 int nxt[maxn],lst[maxn];
     17 
     18 int read()
     19 {
     20     char ch = getchar();
     21     int num = 0;
     22     bool fl = 0;
     23     for (; !isdigit(ch); ch = getchar())
     24         if (ch=='-') fl = 1;
     25     for (; isdigit(ch); ch = getchar())
     26         num = (num<<1)+(num<<3)+ch-48;
     27     if (fl) num = -num;
     28     return num;
     29 }
     30 void pushdown(int x)
     31 {
     32     mn[x<<1] = std::min(mn[x<<1], mn[x]);
     33     mn[x<<1|1] = std::min(mn[x<<1|1], mn[x]);
     34 }
     35 void build(int rt, int l, int r)
     36 {
     37     mn[rt] = INF;
     38     if (l==r){
     39         mn[rt] = sgVal[l];
     40         return;
     41     }
     42     int mid = (l+r)>>1;
     43     build(rt<<1, l, mid), build(rt<<1|1, mid+1, r);
     44 }
     45 int query(int rt, int l, int r, int pos)
     46 {
     47     if (l==r) return mn[rt];
     48     int mid = (l+r)>>1;
     49     pushdown(rt);
     50     if (pos <= mid) return query(rt<<1, l, mid, pos);
     51     return query(rt<<1|1, mid+1, r, pos);
     52 }
     53 void update(int rt, int L, int R, int l, int r, int c)
     54 {
     55     if (L <= l&&r <= R){
     56         mn[rt] = std::min(mn[rt], c);
     57         return;
     58     }
     59     int mid = (l+r)>>1;
     60     pushdown(rt);
     61     if (L <= mid) update(rt<<1, L, R, l, mid, c);
     62     if (R > mid) update(rt<<1|1, L, R, mid+1, r, c);
     63 }
     64 int main()
     65 {
     66     n = read(), m = read(), tt = 0;
     67     for (int i=1; i<=n; i++)
     68     {
     69         a[i] = read();
     70         if (a[i] > n) a[i] = n+1;
     71     }
     72     for (int i=1; i<=m; i++)
     73         q[i].l = read(), q[i].r = read(), q[i].id = i;
     74     std::sort(q+1, q+m+1);
     75     for (int i=1; i<=n; i++)
     76     {
     77         hsh[a[i]] = 1;
     78         if (a[i]==tt)
     79             while (hsh[tt]) tt++;
     80         sgVal[i] = tt;
     81     }
     82     for (int i=n; i>=1; i--)
     83     {
     84         tt = a[i];
     85         nxt[i] = lst[tt], lst[tt] = i;
     86     }
     87     build(1, 1, n);
     88     now = 1;
     89     for (int i=1; i<=m; i++)
     90     {
     91         for (; now < q[i].l; now++)
     92         {
     93             if (!nxt[now]) nxt[now] = n+1;
     94             update(1, now, nxt[now]-1, 1, n, a[now]);
     95         }
     96         ans[q[i].id] = query(1, 1, n, q[i].r);
     97     }
     98     for (int i=1; i<=m; i++)
     99         printf("%d
    ",ans[i]);
    100     return 0;
    101 }

    END

  • 相关阅读:
    C#中如何求时间间隔?
    Ilist<T> 转换成 DataSet
    EditPlus 快捷键
    Array和ArrayList的异同点
    sql server 查询数据库中有多少个表
    jquery + Css 模式对话框
    paddingtop、margintop和top的区别
    JQuery之ContextMenu(右键菜单)
    关于TextBox的Enable与ReadOnly属性
    AjaxToollit 3.5 使用整理
  • 原文地址:https://www.cnblogs.com/antiquality/p/9251532.html
Copyright © 2011-2022 走看看