【线段树】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

原文地址:https://www.cnblogs.com/antiquality/p/9251532.html