[BZOJ3585]mex 主席树
3585: mex
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 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
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
Source
主席树,维护权值线段树,维护前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 }
O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~