模板:有旋treap

有旋转的treap,其实rotate比较难理解

没关系,上板子:

题目还是普通平衡树

#include<iostream>
#include<cstdio>
#include<algorithm>
#define MAXN 100005
using namespace std;
int n,opt,x,root=0,np;
struct node{
	int ch[MAXN][2],val[MAXN],size[MAXN],cnt[MAXN],prior[MAXN];
	void update(int now){
		 size[now]=size[ch[now][0]]+size[ch[now][1]]+cnt[now];
	}
	void rotate(int &now,int dir){
		int son=ch[now][dir^1];
		ch[now][dir^1]=ch[son][dir];
		ch[son][dir]=now;
		update(now);
		update(now=son);
	}
	void insert(int &now,int x){
		if(!now){
			now=++np;
			size[now]=cnt[now]=1;
			prior[now]=rand();
			val[now]=x;
			return ;
		}
		size[now]++;
		if(val[now]==x){
			cnt[now]++;
			return ;
		}
		int d=x>val[now];
		insert(ch[now][d],x);
		if(prior[ch[now][d]]<prior[now]) rotate(now,d^1);
	}
	void remove(int &now,int num){
		if(!now) return;
		if(val[now]==num){
			if(cnt[now]>1){
				size[now]--; 
				cnt[now]--; 
				return;
			}
			if(!ch[now][0]||!ch[now][1]){
				now=ch[now][0]+ch[now][1]; 
				return;
			}
			int d=prior[ch[now][1]]<prior[ch[now][0]];
			rotate(now,d^1);
			remove(now,num);
			return;
		}
		size[now]--;
		int d=num>val[now];
		remove(ch[now][d],num);
	}
	int get_rank(int now, int num){
		if(!now) return 0;
		if(num==val[now]) return size[ch[now][0]]+1;
		int d=num>val[now];
		if(d) return size[ch[now][0]]+cnt[now]+get_rank(ch[now][1],num);
		return get_rank(ch[now][0],num);
	}
	int get_k(int now,int k){
		while(now){
			if(k<=size[ch[now][0]]) now=ch[now][0]; 
			else if(k>size[ch[now][0]]+cnt[now]) k-=size[ch[now][0]]+cnt[now],now=ch[now][1];
			else return val[now];
		}
	}
	int get_pre(int now,int num){
		if(!now) return -0x7fffffff;
		if(num<=val[now]) return get_pre(ch[now][0],num);
		return max(val[now],get_pre(ch[now][1],num));
	}
	int get_next(int now,int num){
		if(!now) return 0x7fffffff;
		if(num>=val[now]) return get_next(ch[now][1],num);
		return min(val[now],get_next(ch[now][0],num));
	}
}treap;
int main(){
	scanf("%d",&n);
	while(n--){
		scanf("%d%d",&opt,&x);
		if(opt==1) treap.insert(root,x);
		else if(opt==2) treap.remove(root, x);
		else if(opt==3) printf("%d\n",treap.get_rank(root,x));
		else if(opt==4) printf("%d\n",treap.get_k(root,x));
		else if(opt==5) printf("%d\n",treap.get_pre(root,x));
		else if(opt==6) printf("%d\n",treap.get_next(root,x));
	}
	return 0;
}

 

posted @ 2019-08-06 11:57  xukl21  阅读(126)  评论(0编辑  收藏  举报