关于非旋转treap的学习

非旋转treap的操作基于split和merge操作,其余操作和普通平衡树一样,复杂度保证方式与旋转treap差不多,都是基于一个随机的参数,这样构出的树树高为(logn)

split

作用:将原平衡树分为排名为([1,k]),([k+1,n])的两棵平衡树
实现:
1.如果(x)左儿子的子树大小(size[l]==k),那么(x)左儿子即为([1,k])这个平衡树的根,(x)本身为另一颗平衡树的根
2.如果(x)左儿子的子树大小(size[l]+1==k),那么(x)([1,k])这个平衡树的根,(x)右儿子为另一颗平衡树的根
3.如果是上述情况,直接把左儿子或右儿子接上去就好
4.否则,递归处理,直到出现这两种情况位置

inline void split(int x,int k,int &a,int &b){
	if(!k){a=0;b=x;return ;}
	int l=ch[x][0],r=ch[x][1];
	if(sz[l]==k)ch[x][0]=0,a=l,b=x;
	else if(sz[l]+1==k)ch[x][1]=0,a=x,b=r;
	else if(sz[l]>k)split(l,k,a,ch[x][0]),b=x;
	else split(r,k-sz[l]-1,ch[x][1],b),a=x;
	upd(x);
}

merge

作用:将两棵平衡树合并,合并后参数满足(heap)的性质,且满足平衡树性质.
实现:
我们强制(merge(x,y))(x)的所有节点的关键字都小于所有(y)的关键字,根据关键字合并即可.

inline int merge(int x,int y){
	if(!x||!y)return x+y;
	if(key[x]>key[y]){
		ch[x][1]=merge(ch[x][1],y);
		upd(x);
		return x;
	}
	else{
		ch[y][0]=merge(x,ch[y][0]);
		upd(y);
		return y;
	}
}

insert

(x)的前驱为界,拆原树为两棵树,将左树合并到(x),再将(x)合并到右树

inline void ins(int x){
	v[++cnt]=x;key[cnt]=rand();sz[cnt]=1;
	int l,r;
	split(rt,rank(x)-1,l,r);
	rt=merge(merge(l,cnt),r);
}

delet

(x)为界(split)原树,删除(x)后再合并左右子树

inline void Delet(int x){
	int l,r;
	split(rt,x,l,r);
	split(l,x-1,l,x);
	rt=merge(l,r);
}

标记下放

只需在(merge),(split),(kth),(rank)函数前下放即可

完整代码:

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define RG register
#define il inline
#define iter iterator
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
const int N=100005;
int ch[N][2],sz[N],key[N],cnt=0,v[N],rt;
inline void upd(int x){sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;}
inline void split(int x,int k,int &a,int &b){
	if(!k){a=0;b=x;return ;}
	int l=ch[x][0],r=ch[x][1];
	if(sz[l]==k)ch[x][0]=0,a=l,b=x;
	else if(sz[l]+1==k)ch[x][1]=0,a=x,b=r;
	else if(sz[l]>k)split(l,k,a,ch[x][0]),b=x;
	else split(r,k-sz[l]-1,ch[x][1],b),a=x;
	upd(x);
}
inline int merge(int x,int y){
	if(!x||!y)return x+y;
	if(key[x]>key[y]){
		ch[x][1]=merge(ch[x][1],y);
		upd(x);
		return x;
	}
	else{
		ch[y][0]=merge(x,ch[y][0]);
		upd(y);
		return y;
	}
}
inline int rank(int k){
	int x=rt,ret=1;
	while(x){
		if(k<=v[x])x=ch[x][0];
		else ret+=sz[ch[x][0]]+1,x=ch[x][1];
	}
	return ret;
}
inline int kth(int k){
	int x=rt,sum;
	while(x){
		sum=sz[ch[x][0]];
		if(sum==k-1)return v[x];
		if(sum>=k)x=ch[x][0];
		else x=ch[x][1],k-=sum+1;
	}return 0;
}
inline void ins(int x){
	v[++cnt]=x;key[cnt]=rand();sz[cnt]=1;
	int l,r;
	split(rt,rank(x)-1,l,r);
	rt=merge(merge(l,cnt),r);
}
inline void Delet(int x){
	int l,r;
	split(rt,x,l,r);
	split(l,x-1,l,x);
	rt=merge(l,r);
}
void work()
{
	int n,op,x;
	scanf("%d",&n);
	while(n--){
		scanf("%d%d",&op,&x);
		if(op==1)ins(x);
		else if(op==2)Delet(rank(x));
		else if(op==3)printf("%d
",rank(x));
		else if(op==4)printf("%d
",kth(x));
		else if(op==5)printf("%d
",kth(rank(x)-1));
		else if(op==6)printf("%d
",kth(rank(x+1)));
	}
}

int main()
{
	freopen("pp.in","r",stdin);
	freopen("pp.out","w",stdout);
	work();
	return 0;
}

原文地址:https://www.cnblogs.com/Yuzao/p/8094551.html