[BZOJ3585]mex 主席树

3585: mex

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 1252  Solved: 639
[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

By 佚名提供

 

主席树,维护权值线段树,维护前r棵树的区间最小值(上一次出现位置)

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<algorithm>
 7 #define ls(x) t[x].s[0]
 8 #define rs(x) t[x].s[1]
 9 using namespace std;
10 struct data {
11     int s[2],min;
12 }t[200005*30];
13 int root[200005],sz=0;
14 void insert(int l,int r,int x,int &y,int p,int val) {
15     y=++sz;
16     if(l==r) {t[y].min=val;return;}
17     ls(y)=ls(x);rs(y)=rs(x);
18     int mid=l+r>>1;
19     if(p<=mid) insert(l,mid,ls(x),ls(y),p,val);
20     else insert(mid+1,r,rs(x),rs(y),p,val);
21     t[y].min=min(t[ls(y)].min,t[rs(y)].min);
22 }
23 int query(int l,int r,int x,int val) {
24     if(l==r) return l;
25     int mid=l+r>>1;
26     if(t[ls(x)].min<val) return query(l,mid,ls(x),val);
27     else return query(mid+1,r,rs(x),val);
28 }
29 int n,m;
30 int main() {
31     scanf("%d%d",&n,&m);
32     for(int i=1;i<=n;i++) {
33         int tmp;scanf("%d",&tmp);
34         insert(0,1e8+1,root[i-1],root[i],tmp,i);
35     }
36     for(int i=1;i<=m;i++) {
37         int l,r;scanf("%d%d",&l,&r);
38         printf("%d\n",query(0,1e8+1,root[r],l));
39     }
40 }
View Code

 

 

posted @ 2017-12-20 17:29  wls001  阅读(190)  评论(0编辑  收藏  举报