【线段树】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
2 1 0 2 1
3 3
2 3
2 4
1 2
3 5
Sample Output
1
2
3
0
3
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\n",ans[i]); 100 return 0; 101 }
END