Splay树详细图解

欢迎拜访我的博客大本营

图片应该显示的出来吧。

P3369 【模板】普通平衡树

image

image

image

image

image

image

image

image

image

image

image

image

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 100010, INF = 1e9;

struct Node {
   
	int ch[2];
	int p, v;
	int size;
	int cnt;
}tr[N];

int root, idx;

void pushup(int u) {
   
	tr[u].size = tr[tr[u].ch[0]].size + tr[tr[u].ch[1]].size + tr[u].cnt;
}

void rotate(int x) {
   
	int y = tr[x].p;
	int z = tr[y].p;
	int k = (tr[y].ch[1] == x);
	
	tr[y].ch[k] = tr[x].ch[k ^ 1], tr[tr[x].ch[k ^ 1]].p = y;
	tr[x].ch[k ^ 1] = y, tr[y].p = x;
	tr[z].ch[tr[z].ch[1] == y] = x, tr[x].p = z;
	
	pushup(y);
	pushup(x);
}

void splay(int x, int k) {
   
	while (tr[x].p != k) {
   
		int y = tr[x].p;
		int z = tr[y].p;
		
		if (z != k) {
   
			if ((tr[z].ch[1] == y) ^ (tr[y].ch[1] == x)) rotate(x);
			else rotate(y);
		}
		
		rotate(x);
	}
	
	if (!k) root = x;
}

void insert(int x) {
   
	int u = root, p = 0;
	while (u && tr[u].v != x) {
   
		p = u;
		u = tr[u].ch[x > tr[u].v];
	}
	if (u) tr[u].cnt++;
	else {
   
		u = ++idx;
		if (p) tr[p].ch[x > tr[p].v] = u;
		tr[u].p = p;
		tr[u].v = x;
		tr[u].size = 1;
		tr[u].cnt = 1;
	}
	splay(u, 0);
}

void find(int x) {
   
	int u = root;
	while (tr[u].ch[x > tr[u].v] && tr[u].v != x) u = tr[u].ch[x > tr[u].v];
	splay(u, 0);
}

int get_pre(int x) {
   
	find(x);
	if (tr[root].v < x) return root;
	int u = tr[root].ch[0];
	while (tr[u].ch[1]) u = tr[u].ch[1];
	splay(u, 0);
	return u;
}

int get_suc(int x) {
   
	find(x);
	if (tr[root].v > x) return root;
	int u = tr[root].ch[1];
	while (tr[u].ch[0]) u = tr[u].ch[0];
	splay(u, 0);
	return u;
}

void remove(int x) {
   
	int pre = get_pre(x);
	int suc = get_suc(x);
	
	splay(pre, 0);
	splay(suc, pre);
	
	int del = tr[suc].ch[0];
	if (tr[del].cnt > 1) tr[del].cnt--, splay(del, 0);
	else tr[suc].ch[0] = 0, splay(suc, 0);
}

int get_rank_by_key(int x) {
   
	insert(x);
	int res = tr[tr[root].ch[0]].size;
	remove(x);
	return res;
}

int get_key_by_rank(int k) {
   
	int u = root;
	while (true) {
   
		if (k <= tr[tr[u].ch[0]].size) u = tr[u].ch[0];
		else if (k <= tr[tr[u].ch[0]].size + tr[u].cnt) break;
		else k -= tr[tr[u].ch[0]].size + tr[u].cnt, u = tr[u].ch[1];
	}
	splay(u, 0);
	return tr[u].v;
}

int main() {
   
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	insert(-INF);
	insert(INF);
	
	int T;
	cin >> T;
	while (T--) {
   
		int opt, x;
		cin >> opt >> x;
		if (opt == 1) insert(x);
		else if (opt == 2) remove(x);
		else if (opt == 3) cout << get_rank_by_key(x) << '\n';
		else if (opt == 4) cout << get_key_by_rank(x + 1) << '\n';
		else if (opt == 5) cout << tr[get_pre(x)].v << '\n';
		else cout << tr[get_suc(x)].v << '\n';
	}
	
	return 0;
}

P6136 【模板】普通平衡树(数据加强版)

注意数组要开到 1.1 × 1 0 6 1.1 \times 10 ^ 6 1.1×106

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1100010, INF = (1 << 30) + 1;

struct Node {
   
	int ch[2];
	int p, v;
	
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值