平衡树模版

 1.存储

struct Node{
	int l,r;
	int key,val;
	int cnt,siz;
}tree[N];

l , r 左儿子,右儿子

key 存储的值

val 随机值

cnt 当前值的个数

siz 包含节点的个数

  2.更新父节点

void pushup(int p){
	tree[p].siz=tree[tree[p].l].siz+tree[tree[p].r].siz+tree[p].cnt;
}

当前点包含节点个数为: 左儿子 右儿子 当前数   个数

 3.建立新节点

int get_node(int key){
	idx++;
	tree[idx].key=key;
	tree[idx].val=rand();
	tree[idx].cnt=tree[idx].siz=1;
	return idx;
}

 4.建树

void build(){
	get_node(-INF),get_node(INF);
	root=1,tree[1].r=2;
	pushup(root);
}

 5.左右旋

void zig(int &p){
	int q=tree[p].l;
	tree[p].l=tree[q].r,tree[q].r=p,p=q;
	pushup(tree[p].r),pushup(p);
}

void zag(int &p){
	int q=tree[p].r;
	tree[p].r=tree[q].l,tree[q].l=p,p=q;
	pushup(tree[p].l),pushup(p);
}

  6.插入

void insert(int &p,int key){
	if(!p)p=get_node(key);
	else if(tree[p].key==key)tree[p].cnt++;
	else if(tree[p].key>key){
		insert(tree[p].l,key);
		if(tree[tree[p].l].val>tree[p].val)zig(p);
	}
	else {
		insert(tree[p].r,key);
		if(tree[tree[p].r].val>tree[p].val)zag(p);
	}
	pushup(p);
}

 7. 删除

void remove(int &p,int key){
	if(!p)return;
	if(tree[p].key==key){
		if(tree[p].cnt>1)tree[p].cnt--;
		else if(tree[p].l||tree[p].r){
			if(!tree[p].r||tree[tree[p].l].val>tree[tree[p].r].val){
				zig(p);
				remove(tree[p].r,key);
			}
			else {
				zag(p);
				remove(tree[p].l,key);
			}
		}
		else p=0;
	}
	else if(tree[p].key>key)remove(tree[p].l,key);
	else remove(tree[p].r,key);
	pushup(p);
} 

 8.通过数值找排名

int get_rank_by_key(int p,int key){
	if(!p)return 0;  
	if(tree[p].key==key)return tree[tree[p].l].siz+1;
	if(tree[p].key>key)return get_rank_by_key(tree[p].l,key);
	return tree[tree[p].l].siz+tree[p].cnt+get_rank_by_key(tree[p].r,key);
}

 9.通过排名找数值

int get_key_by_rank(int p,int rank){
	if(!p)return INF; 
	if(tree[tree[p].l].siz>=rank)return get_key_by_rank(tree[p].l,rank);
	if(tree[tree[p].l].siz+tree[p].cnt>=rank)return tree[p].key;
	return get_key_by_rank(tree[p].r,rank-tree[tree[p].l].siz-tree[p].cnt);
}		

 10.找小于x的最大数

int get_pre(int p,int key){        	 			
	if(!p)return -INF;   
	if(tree[p].key>=key)return get_pre(tree[p].l,key);
	return max(tree[p].key,get_pre(tree[p].r,key));
}

 11.找大于x的最小数

int get_next(int p,int key){
	if(!p)return INF;  
	if(tree[p].key<=key)return get_next(tree[p].r,key);
	return min(tree[p].key,get_next(tree[p].l,key));  
}

  

 Luogu P3369:

#include<bits/stdc++.h>

using namespace std;

#define N 100010
#define INF 2100000000

struct Node{
	int l,r;
	int key,val;
	int cnt,siz;
}tree[N];

int root,idx;

void pushup(int p){
	tree[p].siz=tree[tree[p].l].siz+tree[tree[p].r].siz+tree[p].cnt;
}

int get_node(int key){
	idx++;
	tree[idx].key=key;
	tree[idx].val=rand();
	tree[idx].cnt=tree[idx].siz=1;
	return idx;
}

void build(){
	get_node(-INF),get_node(INF);
	root=1,tree[1].r=2;
	pushup(root);
}

void zig(int &p){
	int q=tree[p].l;
	tree[p].l=tree[q].r,tree[q].r=p,p=q;
	pushup(tree[p].r),pushup(p);
}

void zag(int &p){
	int q=tree[p].r;
	tree[p].r=tree[q].l,tree[q].l=p,p=q;
	pushup(tree[p].l),pushup(p);
}

void insert(int &p,int key){
	if(!p)p=get_node(key);
	else if(tree[p].key==key)tree[p].cnt++;
	else if(tree[p].key>key){
		insert(tree[p].l,key);
		if(tree[tree[p].l].val>tree[p].val)zig(p);
	}
	else {
		insert(tree[p].r,key);
		if(tree[tree[p].r].val>tree[p].val)zag(p);
	}
	pushup(p);
}

void remove(int &p,int key){
	if(!p)return;
	if(tree[p].key==key){
		if(tree[p].cnt>1)tree[p].cnt--;
		else if(tree[p].l||tree[p].r){
			if(!tree[p].r||tree[tree[p].l].val>tree[tree[p].r].val){
				zig(p);
				remove(tree[p].r,key);
			}
			else {
				zag(p);
				remove(tree[p].l,key);
			}
		}
		else p=0;
	}
	else if(tree[p].key>key)remove(tree[p].l,key);
	else remove(tree[p].r,key);
	pushup(p);
} 

int get_rank_by_key(int p,int key){
	if(!p)return 0; 
	if(tree[p].key==key)return tree[tree[p].l].siz+1;
	if(tree[p].key>key)return get_rank_by_key(tree[p].l,key);
	return tree[tree[p].l].siz+tree[p].cnt+get_rank_by_key(tree[p].r,key);
}

int get_key_by_rank(int p,int rank){
	if(!p)return INF; 
	if(tree[tree[p].l].siz>=rank)return get_key_by_rank(tree[p].l,rank);
	if(tree[tree[p].l].siz+tree[p].cnt>=rank)return tree[p].key;
	return get_key_by_rank(tree[p].r,rank-tree[tree[p].l].siz-tree[p].cnt);
}										 
										 			
int get_pre(int p,int key){        	 			
	if(!p)return -INF;   
	if(tree[p].key>=key)return get_pre(tree[p].l,key);
	return max(tree[p].key,get_pre(tree[p].r,key));
}

int get_next(int p,int key){
	if(!p)return INF;  
	if(tree[p].key<=key)return get_next(tree[p].r,key);
	return min(tree[p].key,get_next(tree[p].l,key));  
}

int main(){
	build();
	int n;
	cin>>n;
	while(n--){
		int fl,x;
		cin>>fl>>x;
		if(fl==1)insert(root,x);
		else if(fl==2)remove(root,x);
		else if(fl==3)cout<<get_rank_by_key(root,x)<<endl;
		else if(fl==4)cout<<get_key_by_rank(root,x)<<endl;
		else if(fl==5)cout<<get_pre(root,x)<<endl;
		else cout<<get_next(root,x)<<endl;
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值