【模版】Treap

这篇博客详细介绍了Treap数据结构,包括其插入、删除、查找等操作,并展示了如何利用Treap解决相对排名、选取中序第k大节点、查找前驱和后继等问题。文章通过C++代码实现,适合数据结构和算法学习者参考。
摘要由CSDN通过智能技术生成
#include<bits/stdc++.h>
#define mp make_pair
#define PII pair<string,int>
#define pb push_back
#define vec vector
#define All(x) x.begin(),x.end() 
#define INS(x) inserter(x,x.begin())
#define INF 0x3f3f3f3f
using namespace std;
const int mx=5e6+5;
const int mod=1e9+7;
//Task : Treap
//Author : cqbzly
inline int read() {
	int x=0,f=1; char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();}
	while(c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0'; c=getchar();}
	return x*f;
}
int n,m,res,last;
struct node{
	int key,fix,cnt,siz;
	node *ch[2];
};
//内存池 
node tree[mx];
node *Root,*NIL,*ncnt;
int rint(){
	return rand()%mod;
}
void PushUp(node *x) {
	if(x==NIL) return;
	x->siz=x->ch[0]->siz+x->ch[1]->siz+x->cnt;
}
//旋转同时修改当前根 
void Rotate(node *&x,int d) {
	node *y=x->ch[!d];
	x->ch[!d]=y->ch[d];
	y->ch[d]=x;
	x=y;
	PushUp(x->ch[d]);
	PushUp(x);
}
void Init() {
	NIL=&tree[0];
	NIL->ch[0]=NIL->ch[1]=NIL;
	NIL->fix=(1<<30)-1;
	ncnt=&tree[1];
	Root=NIL;
}
node *NewNode(int val) {
	node *p=ncnt++;
	p->key=val;
	p->ch[0]=p->ch[1]=NIL;
	p->cnt=p->siz=1;
	p->fix=rint()%mod;
	return p;
}
void Insert(node *&rt,int val) {
	if(rt==NIL) {
		rt=NewNode(val);
		return;
	}
	if(rt->key==val) {
		rt->cnt++; rt->siz++;
		return;
	}
	int d=(val>=rt->key);
	Insert(rt->ch[d],val);
	if(rt->ch[d]->fix<rt->fix) 
	    Rotate(rt,!d);
	PushUp(rt);
}
//相对排名 
int GetRank(node *rt,int val) {
	if(rt==NIL) return 1;
	if(val==rt->key) return rt->ch[0]->siz+1;
	if(val<rt->key) return GetRank(rt->ch[0],val);
	else return GetRank(rt->ch[1],val)+rt->ch[0]->siz+rt->cnt;
}
//选取中序第 k 大节点 
node *Select(node *rt,int k) {
	if(rt==NIL) return NIL;
	if(k<=rt->ch[0]->siz) return Select(rt->ch[0],k);
	else if(k<=rt->ch[0]->siz+rt->cnt) return rt;
	else return Select(rt->ch[1],k-(rt->ch[0]->siz+rt->cnt));
}
//查找前驱
node *FindPre(int val) {
	int k=GetRank(Root,val);
	node *p=Select(Root,k-1);
	return p;
} 
//查找后继 
node *FindNxt(int val) {
	int k=GetRank(Root,val+1);
	node *p=Select(Root,k);
	return p;
}
//迭代删除 (没有则不删除)
void Delete(node *&rt,int val) {
	//处理叶节点 
	if(rt->ch[0]==NIL&&rt->ch[1]==NIL) {
		if(rt->key==val) {
			rt->cnt--,rt->siz--;
			if(rt->cnt==0) rt=NIL;
		}
		return;
	}
	if(rt->key==val) {
		if(rt->cnt>1) {
			rt->cnt--,rt->siz--;
			return;
		}
		//下旋删除节点 
		else {
			int d=(rt->ch[0]->fix<rt->ch[1]->fix);
			Rotate(rt,d);
			Delete(rt->ch[d],val);
		}
	}
	else {
		int d=(val>=rt->key);
		Delete(rt->ch[d],val);
	}
	PushUp(rt);
}
int main() {
	srand(unsigned(time(0)));
	n=read(),m=read(); Init();
	for(int i=1;i<=n;i++) {
		int x=read();
		Insert(Root,x);
	}
	for(int i=1;i<=m;i++) {
		int op=read(),x=read();
		x^=last;
		if(op==1) {
			Insert(Root,x);
		}
		else if(op==2) {
			Delete(Root,x);
		}
		else if(op==3) {
			last=GetRank(Root,x);
			res^=last;
		}
		//不存在为空的情况 
		else if(op==4) {
			last=Select(Root,x)->key;
			res^=last;
		}
		else if(op==5) {
			last=FindPre(x)->key;
			res^=last;
		}
		else if(op==6) {
			last=FindNxt(x)->key;
			res^=last;
		}
	}
	printf("%d",res);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值