LOJ107 维护全序集【平衡树 非旋treap模板】

传送门


SOL

非旋treap (fhp_treap)板子
(同普通平衡树)


CODE

#include<bits/stdc++.h>
using namespace std;
#define sf scanf
#define pf printf
#define fi first
#define se second
const int maxn=3e5+10;
typedef pair<int,int> T;
int n,pri[maxn],val[maxn],ch[maxn][2],siz[maxn],rt,tot=0;
inline void pushup(int p){siz[p]=siz[ch[p][0]]+siz[ch[p][1]]+1;}
inline int creat(int k){val[++tot]=k;pri[tot]=rand();siz[tot]=1;return tot;}
//megre的前提:两个区间是连续的并且不重叠 
inline int merge(int x,int y){
	if(!x||!y)return x+y;
	if(pri[x]>pri[y]){
		ch[x][1]=merge(ch[x][1],y);
		pushup(x);
		return x;
	}
	else{
		ch[y][0]=merge(x,ch[y][0]);
		pushup(y);
		return y;
	}
}
inline T split(int p,int k){
	if(!p)return make_pair(0,0); 
	T res,tmp;
	if(siz[ch[p][0]]>=k){
	//当前节点在右边的那一部分
		tmp=split(ch[p][0],k);
		ch[p][0]=tmp.se;
		res.fi=tmp.fi;res.se=p;
		pushup(p);	
	}
	else{
	//当前节点在左边的那一部分 
		tmp=split(ch[p][1],k-(siz[ch[p][0]]+1));
		ch[p][1]=tmp.fi;
		res.fi=p;res.se=tmp.se;
		pushup(p);
	}
	return res;
}
inline int rank(int p,int k){
	if(!p)return 1;
	if(val[p]<k)return siz[ch[p][0]]+1+rank(ch[p][1],k);
	else return rank(ch[p][0],k);
}
inline int kth(int p,int k){
	if(!p)return -1;
	if(siz[ch[p][0]]+1==k)return val[p];
	if(siz[ch[p][0]]>=k) return kth(ch[p][0],k);
	else return kth(ch[p][1],k-(siz[ch[p][0]]+1));
}
inline void add(int vl){
	int p=creat(vl),k=rank(rt,vl)-1;
	T t=split(rt,k);
	rt=merge(merge(t.fi,p),t.se);
}
inline void delt(int vl){
	int k=rank(rt,vl);
	T t=split(rt,k);
	rt=merge(split(t.fi,k-1).fi,t.se);
}
inline int pre(int vl){return kth(rt,rank(rt,vl)-1);}
inline int nxt(int vl){return kth(rt,rank(rt,vl+1));}
signed main(){
	srand(time(0));
	sf("%d",&n);
	while(n--){
		int f,x;sf("%d%d",&f,&x);
		if(f==0)add(x);
		if(f==1)delt(x);
		if(f==2)pf("%d\n",kth(rt,x));
		if(f==3)pf("%d\n",rank(rt,x)-1);
		if(f==4)pf("%d\n",pre(x));
		if(f==5)pf("%d\n",nxt(x));
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值