[洛谷P3369]【模板】普通平衡树(Treap/SBT)

题目大意:给你一些操作:

1.插入一个数;

2.删除一个数;

3.输出x是第几小的数;

4.输出第k小的数是几;

5.输出比x小的最大数;

6.输出比x大的最小数。

要你实现它。

解题思路:平衡树模板题。

用Treap/Splay/替罪羊树/pbds(雾)等均可。

我使用简单的Treap实现。

注意在5和6操作时,必须要搜到叶子才停止,否则会遗漏答案。

这里用指针实现,删除操作可能会出现内存浪费。

C++ Code:

#include<cstdio>
#include<cctype>
#include<ctime>
#include<cstdlib>
class treap{
	private:
		struct node{
			node* ch[2];
			int s,x,r,sz;
			node(){
				ch[0]=ch[1]=NULL;
			}
		};
		void update(node*&o){
			o->s=o->sz;
			if(o->ch[0]!=NULL)o->s+=o->ch[0]->s;
			if(o->ch[1]!=NULL)o->s+=o->ch[1]->s;
		}
		void rotate(node*& o,int d){
			node* k=o->ch[d^1];
			o->ch[d^1]=k->ch[d];
			k->ch[d]=o;
			update(o);
			update(k);
			o=k;
		}
	public:
		node* rt;
		void ins(node*&o,int p){
			if(o==NULL){
				o=new node;
				o->s=o->sz=1;
				o->x=p;
				o->r=rand();
				return;
			}
			if(p<o->x){
				ins(o->ch[0],p);
				if(o->ch[0]->r<o->r)rotate(o,1);
			}else
			if(p>o->x){
				ins(o->ch[1],p);
				if(o->ch[1]->r<o->r)rotate(o,0);
			}else ++o->sz;
			update(o);
		}
		void del(node*&o,int p){
			if(o==NULL)return;
			if(o->x==p){
				if(o->sz>1)--o->sz;else
				if(o->ch[0]==NULL&&o->ch[1]==NULL)o=NULL;else
				if(o->ch[0]!=NULL&&o->ch[1]!=NULL){
					if(o->ch[0]->r<o->ch[1]->r){
						rotate(o,1);
						del(o->ch[1],p);
					}else{
						rotate(o,0);
						del(o->ch[0],p);
					}
				}else
				if(o->ch[0]==NULL)o=o->ch[1];else o=o->ch[0];
				if(o!=NULL)update(o);
			}else{
				if(p<o->x)del(o->ch[0],p);else del(o->ch[1],p);
				if(o!=NULL)update(o);
			}
		}
		int find(node* o,int p){
			if(o==NULL)return 0;
			int l=0;
			if(o->ch[0]!=NULL)l=o->ch[0]->s;
			if(o->x==p)return l+1;
			if(o->x>p)return find(o->ch[0],p);
			return l+o->sz+find(o->ch[1],p);
		}
		int kth(node* o,int k){
			if(o==NULL)return 0;
			int l=0;
			if(o->ch[0]!=NULL)l=o->ch[0]->s;
			if(k>l&&k<=l+o->sz)return o->x;
			if(k<=l)return kth(o->ch[0],k);
			return kth(o->ch[1],k-l-o->sz);
		}
		void pre(node* o,int p,int& ans){
			if(o==NULL)return;
			if(o->x<p){
				if(ans<o->x)ans=o->x;
				if(o->ch[1]!=NULL)pre(o->ch[1],p,ans);
			}else
			if(o->ch[0]!=NULL)pre(o->ch[0],p,ans);
		}
		void nxt(node* o,int p,int& ans){
			if(o==NULL)return;
			if(o->x>p){
				if(ans>o->x)ans=o->x;
				if(o->ch[0]!=NULL)nxt(o->ch[0],p,ans);
			}else
			if(o->ch[1]!=NULL)nxt(o->ch[1],p,ans);
		}
		treap(){rt=NULL;}
}Treap;
inline int readint(){
	char c=getchar();
	bool b=false;
	for(;!isdigit(c);c=getchar())b=c=='-';
	int d=0;
	for(;isdigit(c);c=getchar())
	d=(d<<3)+(d<<1)+(c^'0');
	return b?-d:d;
}
int main(){
	srand(2333);
	for(int n=readint();n--;){
		int opt=readint(),x=readint();
		if(opt==1)Treap.ins(Treap.rt,x);else
		if(opt==2)Treap.del(Treap.rt,x);else
		if(opt==3)printf("%d
",Treap.find(Treap.rt,x));else
		if(opt==4)printf("%d
",Treap.kth(Treap.rt,x));else
		if(opt==5){
			int ans=-2000000000;
			Treap.pre(Treap.rt,x,ans);
			printf("%d
",ans);
		}else{
			int ans=2000000000;
			Treap.nxt(Treap.rt,x,ans);
			printf("%d
",ans);
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/Mrsrz/p/8444135.html