【模板】SBT 普通平衡树

平衡树模板,高中学的时候照着别人的代码写的。

#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=100100;int M;
struct ss{
	int key[N],s[N],left[N],right[N];
	int rt,nodecnt;
	void clear(){
        rt=0,nodecnt=0;
        memset(key,0,sizeof(key));
        memset(s,0,sizeof(s));
        memset(left,0,sizeof(left));
        memset(right,0,sizeof(right));
    }; 
	void z_x(int &p){//左旋 
		int k=right[p];
		right[p]=left[k];left[k]=p;
		s[k]=s[p];
		s[p]=s[right[p]]+s[left[p]]+1;
		p=k; 
	}void y_x(int &p){//右旋
		int k=left[p];
		left[p]=right[k];right[k]=p;
		s[k]=s[p];
		s[p]=s[right[p]]+s[left[p]]+1;
		p=k;
	}
	//旋比较简单,不注释了。
	void peace(int &p,bool flag){
		if(!flag){//加到了左子树 
			if(s[left[left[p]]]>s[right[p]]) y_x(p);
			else {//加到了左子树的右子树 
				if(s[right[left[p]]]>s[right[p]]){
					z_x(left[p]);y_x(p);
				}else return ;
			}
		}else{//反之 
			if(s[right[right[p]]]>s[left[p]])
				z_x(p);
			else{
				if(s[left[right[p]]]>s[left[p]]){
					y_x(right[p]);z_x(p);
				}else return;
			}
		}
		peace(left[p],false);
		peace(right[p],true);
		peace(p,true);
		peace(p,false);
	}//平衡...也比较简单,不说了。
	void insert(int &p,int x){//加入一个值为x的数 
		if(!p){
			p=++nodecnt;key[p]=x;s[p]=1;
			return;
		}s[p]++;
		if(x<key[p]) insert(left[p],x);
		else insert(right[p],x);
		peace(p,x>=key[p]);
	}//插入一个数....也比找到合适的位置就好。
	
	int del(int &p,int x){//删除一个值为x的数 
		s[p]--;int tmp;
		if(x==key[p]||(x<key[p]&&!left[p])
		||(x>key[p]&&!right[p])){
			tmp=key[p];
			if(!left[p]||!right[p])
				p=left[p]+right[p];
			else key[p]=del(left[p],key[p]+1);
			return tmp;
		}if(x<key[p]) tmp=del(left[p],x);
		else tmp=del(right[p],x);
		return tmp;
	}
	int rank(int &p,int x){//x的排名 
		if(!p) return 1;int tmp=0;
		if(x<=key[p]) tmp=rank(left[p],x);
		else tmp=s[left[p]]+1+rank(right[p],x);
		return tmp;
	}
	int select(int &p,int x){//第x小的数 
		if(x==s[left[p]]+1) return key[p];
		if(x<=s[left[p]]) return select(left[p],x);
		else return select(right[p],x-1-s[left[p]]);
	}
	int pred(int &p,int x){//x的前驱
		if(!p) return x;int tmp;
		if(x<=key[p]) tmp=pred(left[p],x);
		else{tmp=pred(right[p],x);if(tmp==x)tmp=key[p];}
		return tmp;
	}int succ(int &p,int x){//x的后驱
		if(!p)return x;int tmp;
		if(x>=key[p]) tmp=succ(right[p],x);
		else{tmp=succ(left[p],x);if(tmp==x)tmp=key[p];}
		return tmp;
	}	
}T;
int main(){
	T.clear();scanf("%d",&M);
	int &rt=T.rt=0;
	while(M--){
		int opt,x;scanf("%d%d",&opt,&x);
		if(opt==1) T.insert(rt,x);
		else if(opt==2) T.del(rt,x);
		else if(opt==3) printf("%d\n",T.rank(rt,x));
		else if(opt==4) printf("%d\n",T.select(rt,x));
		else if(opt==5) printf("%d\n",T.pred(rt,x));
		else if(opt==6) printf("%d\n",T.succ(rt,x)); 
	}return 0;
}

删除操作注:
一直往下找,直到找到这个数,然后把这个数删了,
继续按顺序往下找,直到找到一个可以代替删掉的那个数位置的数,然后返回。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GoesM

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值