带旋平衡树treap(tyvj1728普通平衡树)

平衡树treap(带旋treap)

带旋treap
注意左右旋转可以合并,d=1时 左儿子上旋至根节点,d==0时右儿子上旋至根节点
代码见下:

void zhuan(int &x,int d){//旋转,d=1是左儿子上旋
		int son=t[x].ch[d];
		t[x].ch[d]=t[son].ch[d^1];
		t[son].ch[d^1]=x;
		up(x),up(x=son); 
	}
有zz问我ac没有,废话,我都发博客了还能没ac吗?(滑稽)
全部代码见下
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5,inf=0x3f3f3f3f; 
inline int get(){
	int res=0,flag=1;char c=getchar();
	while(c<'0'||c>'9'){
		if(c=='-')flag=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		res=res*10+c-'0';
		c=getchar();
	}
	return res*flag;
}
struct node{
	int ch[2],cnt,size,val,rd;//依次为左右儿子,有几个这么大的数,根和子节点总个数,值,随机排名 
}t[N]; 
int tot=0;
struct treap{
	#define ls t[x].ch[0]
	#define rs t[x].ch[1]
	void up(int x){//向上更新size 
		t[x].size=t[t[x].ch[0]].size+t[t[x].ch[1]].size+t[x].cnt;
	}		
	void zhuan(int &x,int d){//旋转,d=1是左儿子上旋
		int son=t[x].ch[d];
		t[x].ch[d]=t[son].ch[d^1];
		t[son].ch[d^1]=x;
		up(x),up(x=son); 
	}
	void insert(int &x,int val){//插入 
		if(!x){
			x=++tot;
			t[x].cnt=t[x].size=1;
			t[x].val=val;t[x].rd=rand();
			return ;
		}
		t[x].size++;
		if(t[x].val==val){
			t[x].cnt++;return;
		} 
		int d=t[x].val<val;insert(t[x].ch[d],val);
		if(t[x].rd>t[t[x].ch[d]].rd)zhuan(x,d);
	} 
	void shan(int &x,int val){//删数 
		if(!x)return ;
		if(t[x].val==val){
			if(t[x].cnt>1){
				t[x].cnt--;t[x].size--;
				return ;
			}
			bool d=t[ls].rd>t[rs].rd;
			if(!ls||!rs)x=ls+rs;
			else zhuan(x,d),shan(x,val);
		}
		else t[x].size--,shan(t[x].ch[t[x].val<val],val);
	} 
	int rank(int x,int val){//k的排名 
		if(!x)return 0;
		if(t[x].val==val)return t[ls].size+1;
		if(t[x].val>val)return rank(ls,val);
		return rank(rs,val)+t[ls].size+t[x].cnt;	
	} 
	int kth(int root,int k){//k大 
		int x=root;
		while(1){
			if(k<=t[ls].size)x=ls;
			else if(k>t[ls].size+t[x].cnt)
				k-=t[ls].size+t[x].cnt,x=rs;
			else return t[x].val;
		}
	} 
	int pre(int x,int val){//前驱 
		if(!x)return -inf;
		if(t[x].val>=val)return pre(ls,val);
		return max(pre(rs,val),t[x].val); 
	} 
	int nxt(int x,int val){//后继 
		if(!x)return inf;
		if(t[x].val<=val)return nxt(rs,val);
		return min(nxt(ls,val),t[x].val);
	}
}tr;
int main(){
	int n=get(),rt=0;
	while(n--){
		int q=get(),x=get(); 
		if(q==1)tr.insert(rt,x);
		if(q==2)tr.shan(rt,x);
		if(q==3)printf("%d\n",tr.rank(rt,x));//注意是rt不是1或0
		if(q==4)printf("%d\n",tr.kth(rt,x));
		if(q==5)printf("%d\n",tr.pre(rt,x));
		if(q==6)printf("%d\n",tr.nxt(rt,x)); 
	}
	return 0;
} 

我wa的点:

555:

1、主程序中时rt不是0或1

2、读优要带负数!!!!!

完结散花

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值