线段树--第k小数

【平衡树】第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 9
1 8
1 6
3 10
2 4
3 3

Sample Output

0
7

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值