粗糙splay板子

9 篇文章 0 订阅
1 篇文章 0 订阅

存一个。

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e5 + 5;

struct Splay {
	//f[i]表示i的父结点,ch[i][0]表示i的左儿子,ch[i][1]表示i的右儿子.
	//key[i]表示i的关键字(即结点i代表的那个数字),cnt[i]表示i结点的关键字出现的次数(相当于权值).
	//size[i]表示包括i的这个子树的大小;sz为整棵树的大小,root为整棵树的根。
	int ch[maxn][2], fa[maxn];
	int size[maxn], cnt[maxn], key[maxn];
	int root, sz;

	void init() {
		root = 0;
		sz = 1;
	}

	void clear(int x) {
		fa[x] = ch[x][0] = ch[x][1] = 0;
		size[x] = cnt[x] = key[x] = 0;
	}

	bool get(int x) {
		return ch[fa[x]][1] == x;
	}

	void update(int x) {
		if(!x) {
			return;
		}
		size[x] = cnt[x];
		if(ch[x][0]) {
			size[x] += size[ch[x][0]];
		}
		if(ch[x][1]) {
			size[x] += size[ch[x][1]];
		}
	}

	void rotate(int x) {
		int old = fa[x], oldf = fa[old];
		int tar = get(x);
		ch[old][tar] = ch[x][tar ^ 1];
		fa[ch[old][tar]] = old;
		ch[x][tar ^ 1] = old;
		fa[old] = x;
		fa[x] = oldf;
		if(oldf) {
			ch[oldf][ch[oldf][1] == old] = x;
		}
		update(old);
		update(x);
	}

	int newNode(int x, int f) {
		fa[sz] = f;
		ch[sz][0] = ch[sz][1] = 0;
		root = sz;
		size[sz] = cnt[sz] = 1;
		key[sz] = x;
		return sz++;
	}

	void splay(int x) {
		for (int f; f = fa[x]; rotate(x))
		if(fa[f]) {
			if(get(x) == get(f)) {
				rotate(f);
			} else {
				rotate(x);
			}
		}
		root = x;
	}

	void insert(int x) {
		if(root == 0) {
			newNode(x, 0);
			return;
		}
		int now = root, f = 0;
		while(1) {
			if(x == key[now]) {
				++cnt[now];
				update(now);
				update(f);
				splay(now);
				break;
			}
			f = now;
			now = ch[now][key[now] < x];
			if(now == 0) {
				int nq = newNode(x, f);
				ch[f][key[f] < x] = nq;
				update(f);
				splay(nq);
				break;
			}
		}
	}

	int find(int x) {
		int now = root, ans = 0;
		while(1) {
			if(x < key[now]) {
				now = ch[now][0];
			} else {
				ans += ch[now][0] ? size[ch[now][0]] : 0;
				if(x == key[now]) {
					splay(now);
					return ans + 1;
				}
				ans += cnt[now];
				now = ch[now][1];
			}
		}
	}

	int findx(int x) {
		int now = root;
		while(1) {
			if(ch[now][0] && x <= size[ch[now][0]]) {
				now = ch[now][0];
			} else {
				int tmp = (ch[now][0] ? size[ch[now][0]] : 0) + cnt[now];
				if(x <= tmp) {
					return key[now];
				}
				x -= tmp;
				now = ch[now][1];
			}
		}
	}

	int pre() {
		int now = ch[root][0];
		while(ch[now][1]) {
			now = ch[now][1];
		}
		return now;
	}

	int next() {
		int now = ch[root][1];
		while(ch[now][0]) {
			now = ch[now][0];
		}
		return now;
	}

	void del(int x) {
		find(x);
		if(cnt[root] > 1) {
			--cnt[root];
			update(root);
			return;
		}
		if(!ch[root][0] && !ch[root][1]) {
			clear(root);
			root = 0;
			return;
		}
		int old = root;
		if(!ch[root][0]) {
			root = ch[root][1];
			fa[root] = 0;
			clear(old);
			return;
		}
		if(!ch[root][1]) {
			root = ch[root][0];
			fa[root] = 0;
			clear(old);
			return;
		}
		splay(pre());
		ch[root][1] = ch[old][1];
		fa[ch[old][1]] = root;
		clear(old);
		update(root);
	}

} sp;


int main() {
	int n, opt, x;
	scanf("%d", &n);
	sp.init();
	for (int i = 1; i <= n; ++i) {
		scanf("%d%d", &opt, &x);
		switch(opt) {
		case 1:
			sp.insert(x);
			break;
		case 2:
			sp.del(x);
			break;
		case 3:
			printf("%d\n", sp.find(x));
			break;
		case 4:
			printf("%d\n", sp.findx(x));
			break;
		case 5:
			sp.insert(x);
			printf("%d\n", sp.key[sp.pre()]);
			sp.del(x);
			break;
		case 6:
			sp.insert(x);
			printf("%d\n", sp.key[sp.next()]);
			sp.del(x);
			break;
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值