FHQ Treap

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FHQ Treap相关的知识,希望对你有一定的参考价值。

FHQ Treap

1.有旋Treap​

一些数组定义

int sum,R,num[N],sz[N],son[N][2],rd[N];

s u m sum sum结点数

R R R根结点编号

n u m [ ] num[] num[]当前结点出现的次数(与该结点值相同的个数)

s z [ ] sz[] sz[]该结点的子树大小

s o n [ ] [ ] son[][] son[][]记录结点的左右儿子

r d [ ] rd[] rd[]该结点的随机值,用于维护二叉堆 H e a p Heap Heap.

向上合并更新父亲信息

il void re(int p){
	sz[p]=sz[son[p][0]]+sz[son[p][1]]+num[p];
}

旋转维护Heap

il void rot(int &p,int d){
	int k=son[p][d^1]; //左旋取儿子,右选取左儿子.
	son[p][d^1]=son[p][d]; //更新根结点的左儿子右为k的左儿子
	son[k][d]=p;//k的左儿子设为p
	re(p),re(k),p=k;更新p,k信息,根更新为k.
}
  • 插入
  • 删除
  • 根据值找排名
  • 根据排名找值
  • 前驱
  • 后继

基本操作

void ins(int &p,int x){
	if(!p){ //为空结点直接新建
		p=++sum,sz[p]=num[p]=1;
		v[p]=x,rd[p]=rand();return;
	}
	if(v[p]==x){ //重复 更新num,sz
		num[p]++,sz[p]++;return;
	}
	int d=x>v[p]; //往子树插入
	ins(son[p][d],x);  
	if(rd[p]<rd[son[p][d]]) rot(p,d^1); //维护Max Heap
	re(p);
}
void del(int &p,int x){
	if(!p) return; //为空直接返回
	if(x!=v[p]) del(son[p][x>v[p]],x); //往子树找
	else { 
		if(!son[p][0]&&!son[p][1]){ //叶子直接更新
			num[p]--,sz[p]--;
			if(!num[p]) p=0;  //为空删除 p=0
		}
		else if(son[p][0]&&!son[p][1]){ //右旋找右子树
			rot(p,1);
			del(son[p][1],x);
		}
		else if(!son[p][0]&&son[p][1]){ //左旋找左子树
			rot(p,0);
			del(son[p][0],x);
		}
		else { //找到rd较大的往该子树找
			int d=rd[son[p][0]]>rd[son[p][1]];
			rot(p,d);del(son[p][d],x);
		}
	}
	re(p);
}
int rk(int p,int x){
    if (!p) return 0;
    if (v[p]==x) return sz[son[p][0]]+1;
    if (v[p]<x) return sz[son[p][0]]+num[p]+rk(son[p][1],x);
    if (v[p]>x) return rk(son[p][0],x);
}
int find(int p,int x){
    if (!p) return 0;
    if (sz[son[p][0]]>=x) return find(son[p][0],x);
    else if (sz[son[p][0]]+num[p]<x)
        return find(son[p][1],x-num[p]-sz[son[p][0]]);
    else return v[p];
}
int pre(int p,int x){
    if (!p) return -inf;
    if (v[p]>=x) return pre(son[p][0],x);
    else return max(v[p],pre(son[p][1],x));
}
int suf(int p,int x){
    if (!p) return inf;
    if (v[p]<=x) return suf(son[p][1],x);
    else return min(v[p],suf(son[p][0],x));
}

完整版

#define il inline
int sum,R,num[N],sz[N],son[N][2],rd[N],v[N];
il void re(int p){
	sz[p]=sz[son[p][0]]+sz[son[p][1]]+num[p];
}
il void rot(int &p,int d){
	int k=son[p][d^1];
	son[p][d^1]=son[k][d];
	son[k][d]=p;
	re(p),re(k),p=k;
}
void ins(int &p,int x){
	if(!p){
		p=++sum,sz[p]=num[p]=1;
		v[p]=x,rd[p]=rand();return;
	}
	if(v[p]==x){
		num[p]++,sz[p]++;return;
	}
	int d=x>v[p];
	ins(son[p][d],x);
	if(rd[p]<rd[son[p][d]]) rot(p,d^1);
	re(p);
}
void del(int &p,int x){
	if(!p) return;
	if(x!=v[p]) del(son[p][x>v[p]],x);
	else {
		if(!son[p][0]&&!son[p][1]){
			num[p]--,sz[p]--;
			if(!num[p]) p=0; 
		}
		else if(son[p][0]&&!son[p][1]){
			rot(p,1);
			del(son[p][1],x);
		}
		else if(!son[p][0]&&son[p][1]){
			rot(p,0);
			del(son[p][0],x);
		}
		else {
			int d=rd[son[p][0]]>rd[son[p][1]];
			rot(p,d);del(son[p][d],x);
		}
	}
	re(p);
}
int rk(int p,int x){
    if (!p) return 0;
    if (v[p]==x) return sz[son[p][0]]+1;
    if (v[p]<x) return sz[son[p][0]]+num[p]+rk(son[p][1],x);
    if (v[p]>x) return rk(son[p][0],x);
}
int find(int p,int x){
    if (!p) return 0;
    if (sz[son[p][0]]>=x) return find(son[p][0],x);
    else if (sz[son[p][0]]+num[p]<x)
        return find(son[p][1],x-num[p]-sz[son[p][0]]);
    else return v[p];
}
int pre(int p,int x){
    if (!p) return -inf;
    if (v[p]>=x) return pre(son[p][0],x);
    else return max(v[p],pre(son[p][1],x));
}
int suf(int p,int x){
    if (!p) return inf;
    if (v[p]<=x) return suf(son[p][1],x);
    else return min(v[p],suf(son[p][0],x));
}

2.无旋FHQ Treap

按权值分裂

int R; //全局定义初始化为0
int w[N],rd[N],sz[N],son[N][2],cnt; //定义在结构体内

w [ ] w[] w[]结点权值

r d [ ] rd[] rd[]结点的修正值,维护堆

s z [ ] sz[] sz[]结点子树大小

s o n [ ] [ ] son[][] son[][]记录左右儿子

c n t cnt cnt结点总数

向上合并信息

inline void re(int x){sz[x]=sz[son[x][0]]+sz[son[x][1]]+1;}

创建新结点

inline int newnode(int x){w[++cnt]=x,sz[cnt]=1,rd[cnt]=rand();return cnt;}

分裂

	void split(int i,int k,int &x,int &y){if(!i) {x=y=0;return;} //如果i为空 左右子树=0 返回
           //w[i]<=k 把i丢进左子树 左子树的虚拟结点为右儿子,递归
		if(w[i]<=k以上是关于FHQ Treap的主要内容,如果未能解决你的问题,请参考以下文章

算法学习Fhq-Treap(无旋Treap)

浅谈fhq treap

fhq-Treap 文艺平衡树代码记录

平衡树合集(Treap,Splay,替罪羊,FHQ Treap)

模板fhq-treap

fhq-Treap原理