c++普通平衡树(treap)模版,板子

【模板】普通平衡树

题目描述

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

  1. 插入 x x x
  2. 删除 x x x 数(若有多个相同的数,因只删除一个)
  3. 查询 x x x 数的排名(排名定义为比当前数小的数的个数 + 1 +1 +1 )
  4. 查询排名为 x x x 的数
  5. x x x 的前驱(前驱定义为小于 x x x,且最大的数)
  6. x x x 的后继(后继定义为大于 x x x,且最小的数)

输入格式

第一行为 n n n,表示操作的个数,下面 n n n 行每行有两个数 opt \text{opt} opt x x x opt \text{opt} opt 表示操作的序号( $ 1 \leq \text{opt} \leq 6 $ )

输出格式

对于操作 3 , 4 , 5 , 6 3,4,5,6 3,4,5,6 每行输出一个数,表示对应答案

样例 #1

样例输入 #1

10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598

样例输出 #1

106465
84185
492737

提示

【数据范围】
对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 1 0 5 1\le n \le 10^5 1n105 ∣ x ∣ ≤ 1 0 7 |x| \le 10^7 x107

来源:Tyvj1728 原名:普通平衡树

在此鸣谢

#include
#define LL long long
#define PP pair <int, int>
using namespace std;
const int N = 1e5 + 10;
struct Treap {
	int l, r, val, pri, num, size;//左右子节点,值,优先级,重复个数,跟的子树大小 
} tree[N];
int T, cnt;
int root;
inline int read () {
	int s = 0, f = 1;
	char ch = getchar ();
	while (ch < '0' || ch > '9') {
		if (ch == '-')
			f = -1;
		ch = getchar ();
	}
	while (ch >= '0' && ch <= '9') {
		s = (s << 1) + (s << 3) + (ch ^ '0');
		ch = getchar ();
	}
	return s * f;
}
void write (int x) {
    if (x < 0) {
    	putchar ('-');
		x = -x;
	}
    if (x > 9) 
		write (x / 10);
    putchar (x % 10 + '0');
}
inline int New (int val) {//生成新节点 
	tree[ ++ cnt].val = val;//点权 
	tree[cnt].pri = rand ();//给一个随机数作为优先级 
	tree[cnt].num = tree[cnt].size = 1;//子树大小和重复个数均为1 
	tree[cnt].l = tree[cnt].r = 0;//没有左右节点 
	return cnt;
}
inline void Update (int p) {//更新子树大小
	tree[p].size = tree[tree[p].l].size + tree[tree[p].r].size + tree[p].num;//当前子树的大小为左子树的大小加右子树大小叫重复的个数 
}
inline void zig (int &p) {//右旋 
	int q = tree[p].l;
	tree[p].l = tree[q].r;
	tree[q].r = p;
	tree[q].size = tree[p].size;
	Update (p);
	p = q;
}
inline void zag (int &p) {//左旋 
	int q = tree[p].r;
	tree[p].r = tree[q].l;
	tree[q].l = p;
	tree[q].size = tree[p].size;
	Update (p);
	p = q;
}
void Insert (int &p, int val) {//在p的子树中插入val 
	if (!p) {//如果没有,则新建一个 
		p = New (val);
		return;
	}
	tree[p].size ++ ;
	if (val == tree[p].val) {
		tree[p].num ++ ;
		return;	
	}
	if (val < tree[p].val) {
		Insert (tree[p].l, val);
		if (tree[p].pri < tree[tree[p].l].pri) zig (p);
	}
	if (val > tree[p].val) {
		Insert (tree[p].r, val);
		if (tree[p].pri < tree[tree[p].r].pri) zag (p);
	}
}
void Delete (int &p, int val) {//在p的子树中删除val
	if (!p) return;
	tree[p].size -- ;
	if (val == tree[p].val) {
		if (tree[p].num > 1) {
			tree[p].num -- ;
			return;
		}
		if (!tree[p].l || !tree[p].r) 
			p = tree[p].l + tree[p].r;
		else if (tree[tree[p].l].pri > tree[tree[p].r].pri) {
			zig (p);
			Delete (tree[p].r, val);
		}
		else {
			zag (p);
			Delete (tree[p].l, val);
		}
		return;
	} 
	if (val < tree[p].val) Delete (tree[p].l, val);
	if (val > tree[p].val) Delete (tree[p].r, val);
}
inline int Getpre (int val) {//找前驱
	int p = root;
	int res = 0;
	while (p) {
		if (tree[p].val < val) {
			res = tree[p].val;
			p = tree[p].r;
		}
		else p = tree[p].l;
	} 
	return res;
}
inline int Getnext (int val) {//找后继
	int p = root;
	int res = 0;
	while (p) {
		if (tree[p].val > val) {
			res = tree[p].val;
			p = tree[p].l;
		}
		else p = tree[p].r;
	} 
	return res;
}
int getRanking (int p, int val) {//根据val查找排名
	if (!p) return 0;
	if (tree[p].val == val) return tree[tree[p].l].size + 1;
	if (val < tree[p].val) return getRanking (tree[p].l, val);
	if (val > tree[p].val) return getRanking (tree[p].r, val) + tree[tree[p].l].size + tree[p].num;
}
int UseRankingfindval (int p, int rank) {//根据排名rank查找val
	if (!p) return 0;
	if (tree[tree[p].l].size >= rank) return UseRankingfindval (tree[p].l, rank);
	if (tree[tree[p].l].size + tree[p].num >= rank) return tree[p].val;
	return UseRankingfindval (tree[p].r, rank - tree[tree[p].l].size - tree[p].num);
}
int main () {
	T = read ();
	register int op, x;
	while (T -- ) {
		op = read (), x = read ();
		if (op == 1) Insert (root, x);
		if (op == 2) Delete (root, x);
		if (op == 3) write (getRanking (root, x)), puts ("");
		if (op == 4) write (UseRankingfindval (root, x)), puts ("");
		if (op == 5) write (Getpre (x)), puts ("");
		if (op == 6) write (Getnext (x)), puts ("");
	}
	return 0;
}

你可能感兴趣的:(数据结构,c++,算法,图论)