Loading

学习笔记(5)FHQ

又称“无旋 Treap”

主要通过分裂操作 \((split)\) 与合并操作 \((merge)\)维护 \(bst\) 的性质,在进行插入、删除、查询等操作时,通过权值分裂/排名分裂的方式将原平衡树分裂为 \(x\),\(y\) 两颗树进行操作(结合子树的 \(siz\)),后合并分裂的子树

例题

模板:\(P3369\) 【模板】普通平衡树

点击查看代码
#include <bits/stdc++.h>
#define N 100005
using namespace std;
inline int read(){
	char ch = getchar(); int x = 0, f = 1;
	while(!isdigit(ch)){if(ch == '-') f = -1; ch = getchar();}
	while(isdigit(ch)){x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
	return x * f;
}
int n;

struct Node{
	int val, data, siz, cnt;
	int son[2];
};
struct FHQ{
	#define Lc(x) (t[x].son[0])
	#define Rc(x) (t[x].son[1])
	int tot, root, x, y, z;
	Node t[N];
	int add(int k){return t[++tot] = {k, rand(), 1}, tot;}
	void pushup(int now){t[now].siz = 1 + t[Lc(now)].siz + t[Rc(now)].siz;}
	void split(int now, int k, int &a, int &b){
		if(!now){a = b = 0; return;}
		if(k < t[now].val)
			{b = now; split(Lc(now), k, a, Lc(now));}
		else
			{a = now; split(Rc(now), k, Rc(now), b);}
		pushup(now);
	}
	int merge(int a, int b){
		if(!a || !b) return a + b;
		if(t[a].data <= t[b].data)
			{Rc(a) = merge(Rc(a), b); pushup(a); return a;}
		else
			{Lc(b) = merge(a, Lc(b)); pushup(b); return b;}
	}
	int kth(int now, int k){
		while(1){
			if(k <= t[Lc(now)].siz) now = Lc(now);
			else if(k -= t[Lc(now)].siz, k == 1) return now;
			else --k, now = Rc(now);
		}
	}
	void insert(int k){
		split(root, k, x, y);
		root = merge(merge(x, add(k)), y);
	}
	void remove(int k){
		split(root, k, x, y);
		split(x, k - 1, x, z);
		z = merge(Lc(z), Rc(z));
		root = merge(merge(x, z), y);
	}
	int get_rank(int k){
		split(root, k - 1, x, y);
		int res = t[x].siz + 1;
		return root = merge(x, y), res;
	}
	int pre(int k){
		split(root, k - 1, x, y);
		int res = t[kth(x, t[x].siz)].val;
		return root = merge(x, y), res;
	}
	int suf(int k){
		split(root, k, x, y);
		int res = t[kth(y, 1)].val;
		return root = merge(x, y), res;
	}
}T;

int main(){
//	freopen(".in", "r", stdin);
//	freopen(".out", "w", stdout);
	n = read();
	while(n--){
		int opt = read(), x = read();
		switch(opt){
			case 1: T.insert(x); break;
			case 2: T.remove(x); break;
			case 3: printf("%d\n", T.get_rank(x)); break;
			case 4: printf("%d\n", T.t[T.kth(T.root, x)].val); break;
			case 5: printf("%d\n", T.pre(x)); break;
			case 6: printf("%d\n", T.suf(x)); break;
		}
	}
	return 0;
}
posted @ 2024-06-02 21:09  HRcohc  阅读(8)  评论(0编辑  收藏  举报