线段树--第k小数

来源:互联网 发布:淘宝发货地址修改教程 编辑:程序博客网 时间:2024/05/29 13:38

【平衡树】第K小数

Time Limit:150000MS  Memory Limit:1655360K
Case Time Limit:15000MS

Description

  现在已有N个整数,你有以下三种操作: 
A 表示加入一个值为A的整数 
B 表示删除其中值为B的整数 
K 表示输出这些整数中第K小的数

Input

第一行,两个整数N,M,表示最开始有N个整数,总共有M个操作 
第二行用空格隔开的N个整数 
接下来M行,每行表示一个操作

Output

若干行,一行一个整数,表示所求的第K小的数字

Sample Input

5 5 6 2 7 4 91 81 63 102 43 3

Sample Output

07

Hint

注意:如果有多个大小相同的数字,只把他们看做一个数字,如样例。 
若找不到第K小的数,输出0 
数据范围: 
0<=N<=2,000,000 
M<=1,000,000 
-1,000,000,000<=每个整数<=1,000,000,000

#include<cstdio>#include<iostream>#include<algorithm>#include<cstdlib>#include<cstring>struct node{long long ls,rs,sum;};node tree[40000005];long long n,m,tot=1,cnt=0;long long dt=1;bool flag;void add(long long &p,long long l,long long r,long long k){if(k<l||r<k)return;long long mid=(l+r)>>1;if(l==r){if(p==0){p=++tot;if(dt==1){tree[p].sum+=dt;flag=true;}return;}else if(tree[p].sum==0){if(dt==1){tree[p].sum+=dt;flag=true;}return;}else if(tree[p].sum>=1){if(dt==-1){tree[p].sum+=dt;flag=true;}return;}else return;}else if(p==0){p=++tot;} add(tree[p].ls,l,mid,k);add(tree[p].rs,mid+1,r,k);if(flag)tree[p].sum+=dt;}long long query(long long p,long long l,long long r,long long k){long long mid=(l+r)>>1;if(l==r)return l;else if(tree[tree[p].ls].sum>=k)return query(tree[p].ls,l,mid,k);else return query(tree[p].rs,mid+1,r,k-tree[tree[p].ls].sum);}int main(){long long i,j,k;long long temp=1;scanf("%I64d%I64d",&n,&m);for(i=1;i<=n;i++){long long a;scanf("%I64d",&a);a+=1000000001;flag=false;add(temp,1,2000000001,a);if(flag)cnt++;}while(m--){long long x,a;scanf("%I64d%I64d",&x,&a);if(x==1){flag=false;dt=1;a+=1000000001;add(temp,1,2000000001,a);if(flag)cnt++;}if(x==2){flag=false;dt=-1;a+=1000000001;add(temp,1,2000000001,a);if(flag)cnt--;}if(x==3){if(a>cnt)printf("0\n");else printf("%I64d\n",query(temp,1,2000000001,a)-1000000001);}}//printf("%I64d",cnt);}


0 0
原创粉丝点击