Fhq_Treap

理解

注意:
k e y key key 键值
f i x fix fix 优先级

合并

int Merge(int u,int v){
	if(!u||!v) return u+v;
	if(fix[u]<fix[v]){
		ch[u][1]=Merge(ch[u][1],v);
		PushUp(u);
		return u;
	}
	else{
		ch[v][0]=Merge(u,ch[v][0]);
		PushUp(v);	
		return v;
	}
}

在这里插入图片描述

盗图
注意函数只利用了 f i x fix fix 来进行合并,保证堆性质,这里是大根堆,并且两个树要保证 左 ≤ \le
这是一个例子
这是自顶向下的函数
可持久化的时候改变了某些点的父子关系

分裂

void Split(int u,int val,int &x,int &y){
	if(!u){
		x=0,y=0;
		return ;
	}
	if(key[u]<=val)
		x=u,Split(ch[u][1],val,ch[x][1],y);
	else y=u,Split(ch[u][0],val,x,ch[y][0]);
	PushUp(u);
	return ;
}
void Split(int u,int k,int &x,int &y){
	if(!u){
		x=0,y=0;
		return ;
	}
	if(k<=siz[ch[u][0]])
		y=u,Split(ch[u][0],k,x,ch[y][0]);
	else x=u,Split(ch[u][1],k-siz[ch[u][0]]-1,ch[x][1],y);
	PushUp(u);
	return ;
}

在这里插入图片描述
盗图
分裂其实有两种,排名分裂和键值分裂
排名分裂一般用于处理序列问题
权值分裂一般用于处理BST问题(不知道怎么说…)


然后所有操作都水了

关于可持久化

Fhq_Treap的可持久化的图并没有主席树那样清晰易懂(如果有插入节点的话)
但是我们的思想始终是自顶向下
所以分裂操作时候每次新建节点即可
在这里插入图片描述
比如这个图,这些节点都新建了

代码

//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<ctime>
#include<queue>
#include<cstdio>
#include<vector>
#include<climits>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
int read(){
	bool f=0;int x=0;char c=getchar();
	while(c<'0'||'9'<c){if(c=='-')f=1;c=getchar();}
	while('0'<=c&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
	return !f?x:-x;
}
#define MAXN 100000
#define INF 0x3f3f3f3f
namespace Fhq_Treap{
	int Root,ncnt;
	int ch[MAXN+5][2],siz[MAXN+5],key[MAXN+5],fix[MAXN+5];
	inline void PushUp(int u){
		siz[u]=siz[ch[u][0]]+siz[ch[u][1]]+1;
		return ;
	}
	int Newnode(int val){
		siz[++ncnt]=1,key[ncnt]=val,fix[ncnt]=rand(),ch[ncnt][0]=ch[ncnt][1]=0;
		return ncnt;
	}
	int Merge(int u,int v){
		if(!u||!v) return u+v;
		if(fix[u]<fix[v]){
			ch[u][1]=Merge(ch[u][1],v);
			PushUp(u);
			return u;
		}
		else{
			ch[v][0]=Merge(u,ch[v][0]);
			PushUp(v);
			return v;
		}
	}
	void Split(int u,int val,int &x,int &y){
		if(!u){
			x=0,y=0;
			return ;
		}
		if(key[u]<=val)
			x=u,Split(ch[u][1],val,ch[x][1],y);
		else y=u,Split(ch[u][0],val,x,ch[y][0]);
		PushUp(u);
		return ;
	}
	void Insert(int &rt,int val){
		int x,y;
		Split(rt,val,x,y),rt=Merge(Merge(x,Newnode(val)),y);
		return ;
	}
	void Delete(int &rt,int val){
		int x,y,z;
		Split(rt,val-1,x,y),Split(y,val,y,z);
		y=Merge(ch[y][0],ch[y][1]);
		rt=Merge(Merge(x,y),z);
		return ;
	}
	int GetRank(int &rt,int val){
		int x,y;
		Split(rt,val-1,x,y);
		int ret=siz[x]+1;
		rt=Merge(x,y);
		return ret;
	}
	int Kth(int u,int k){
		while(1){
			if(k<=siz[ch[u][0]]) u=ch[u][0];
			else if(k==siz[ch[u][0]]+1) break;
			else k-=siz[ch[u][0]]+1,u=ch[u][1];
		}
		return u;
	}
	int FindPre(int &rt,int val){
		int x,y;
		Split(rt,val-1,x,y);
		int ret=key[Kth(x,siz[x])];
		rt=Merge(x,y);
		return ret;
	}
	int FindNxt(int &rt,int val){
		int x,y;
		Split(rt,val,x,y);
		int ret=key[Kth(y,1)];
		rt=Merge(x,y);
		return ret;
	}
}
using namespace Fhq_Treap;
/*插入x 删除x 查x排名 查排名为x x前驱 x后继*/
int main(){
	srand(time(NULL));
	int T=read();
	while(T--){
		int opt=read(),x=read();
		if(opt==1) Insert(Root,x);
		if(opt==2) Delete(Root,x);
		if(opt==3) printf("%d\n",GetRank(Root,x));
		if(opt==4) printf("%d\n",key[Kth(Root,x)]);
		if(opt==5) printf("%d\n",FindPre(Root,x));
		if(opt==6) printf("%d\n",FindNxt(Root,x));
	}
	return 0;
}

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值