【模板】带旋Treap(指针实现)

版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/82950031

参考题目:LOJ107


解析:

联赛结束后统一更模板题题解。
数组实现看这里


代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const

inline
int getint(){
	re int num;
	re char c;
	while(!isdigit(c=gc()));num=c^48;
	while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
	return num;
}

inline
void outint(int a){
	static char ch[13];
	if(a==0)pc('0');
	if(a<0)pc('-'),a=-a;
	while(a)ch[++ch[0]]=a-a/10*10,a/=10;
	while(ch[0])pc(ch[ch[0]--]^48);
}

cs int INF=0x3f3f3f3f;
typedef struct treap_node *point;
struct treap_node{
	point lc,rc;
	int val,pri,siz,cnt;
	treap_node(){
		lc=rc=NULL;
		val=pri=siz=cnt=0;
	}
	void init(int _val){
		lc=rc=NULL;
		val=_val;
		pri=rand();
		siz=cnt=1;
	}
	void update(){
		siz=(lc==NULL?0:lc->siz)+(rc==NULL?0:rc->siz)+cnt;
	}
};

struct TREAP{
	point root;
	
	void Zig(point &k){
		point y=k->lc;
		k->lc=y->rc;
		y->rc=k;
		y->siz=k->siz;
		k->update();
		k=y;
	}
	
	void Zag(point &k){
		point y=k->rc;
		k->rc=y->lc;
		y->lc=k;
		y->siz=k->siz;
		k->update();
		k=y;
	}
	
	void insert(point &k,cs int &key){
		if(k==NULL){
			k=(point)malloc(sizeof(treap_node));
			k->init(key);
			return ;
		}
		++k->siz;
		if(k->val==key)return (void)(++k->cnt);
		if(key>k->val){
			insert(k->rc,key);
			if(k->rc->pri>k->pri)Zag(k);
		}
		else {
			insert(k->lc,key);
			if(k->lc->pri>k->pri)Zig(k);
		}
	}
	void Insert(cs int &key){insert(root,key);}
	
	void del(point &k,cs int &key){
		if(k==NULL)return ;
		if(k->val==key){
			if(k->cnt>1)--k->cnt,--k->siz;
			else if(!k->lc)/*free(k),*/k=k->rc;//不节约空间可以这样写,
			else if(!k->rc)/*free(k),*/k=k->lc;//如果要节约空间请先用tmp保留要指向的儿子,再用free函数
			else if(k->lc->pri>k->rc->pri)Zig(k),del(k,key);
			else Zag(k),del(k,key);
			return ;
		}
		--k->siz;
		if(key>k->val)del(k->rc,key);
		else del(k->lc,key);
	}
	void Delete(cs int &key){del(root,key);}
	
	int queryrank(cs int &key){
		point k=root;
		int ans=0;
		while(k){
			if(k->val==key)return ans+(k->lc?k->lc->siz:0);
			if(k->val>key)k=k->lc;
			else ans+=(k->lc?k->lc->siz:0)+k->cnt,k=k->rc;
		}
		return ans;
	}
	
	int querykth(int Rank){
		point k=root;
		while(k){
			int res=k->lc?k->lc->siz:0;
			if(res<Rank&&res+k->cnt>=Rank)return k->val;
			if(res>=Rank)k=k->lc;
			else Rank-=res+k->cnt,k=k->rc;
		}
		return 0;
	}
	
	int querypre(cs int &key){
		point k=root;
		int ans=-INF;
		while(k){
			if(k->val>=key)k=k->lc;
			else ans=k->val,k=k->rc;
		}
		return ans==-INF?-1:ans;
	}
	
	int querysuf(cs int &key){
		point k=root;
		int ans=INF;
		while(k){
			if(k->val<=key)k=k->rc;
			else ans=k->val,k=k->lc;
		}
		return ans==INF?-1:ans;
	}
	
}Treap;

int n;

signed main(){
	n=getint();
	while(n--){
		int op=getint(),x=getint();
		int ans;
		switch(op){
			case 0:Treap.Insert(x);break;
			case 1:Treap.Delete(x);break;
			case 2:outint(Treap.querykth(x)),pc('\n');break;
			case 3:outint(Treap.queryrank(x)),pc('\n');break;
			case 4:outint(Treap.querypre(x)),pc('\n');break;
			case 5:outint(Treap.querysuf(x)),pc('\n');break;
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zxyoi_dreamer/article/details/82950031