splay 模板

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int maxn = 1000010;

int sz, root;
int ch[maxn][2], cnt[maxn], size[maxn], p[maxn], key[maxn];

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

inline int get(int x) {
	return ch[p[x]][1] == x;
}

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

inline void rotate(int x) {
	int fa = p[x], gfa = p[p[x]], which = get(x);
	ch[fa][which] = ch[x][which^1];
	p[ch[fa][which]] = fa;
	ch[x][which^1] = fa;
	p[fa] = x;	p[x] = gfa;
	if(gfa)
		ch[gfa][ch[gfa][1] == fa] = x;
	update(fa);	update(x); 
}

inline void splay(int x) {
	for(int fa; fa = p[x]; rotate(x))
		if(p[fa])
			rotate((get(x) == get(fa))?fa:x);
	root = x;
}

inline void insert(int x) {
	int now = root, fa = 0;
	if(now == 0) {
		sz++;	root = sz;	key[sz] = x; 
		ch[sz][0] = ch[sz][1] = p[sz] = 0;
		cnt[sz] = size[sz] = 1;
		return;
	}
	while(1) {
		if(key[now] == x) {
			cnt[now]++;
			update(now);	update(fa);
			splay(now);
			return;
		}
		fa = now, now = ch[now][key[now] < x];
		if(now == 0) {
			sz++;
			ch[sz][0] = ch[sz][1] = 0;
			cnt[sz] = size[sz] = 1;
			p[sz] = fa;	key[sz] = x;
			ch[fa][key[fa] < x] = sz;
			update(fa);
			splay(sz);
			return;
		}
	} 
}

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 temp = (ch[now][0]?size[ch[now][0]]:0) + cnt[now];
			if(x <= temp)
				return key[now];
			x -= temp;
			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) {
	int whatever = find(x);
	if(cnt[root] > 1) {
		cnt[root]--;	update(root);
		return;
	}
	if(!ch[root][0] && !ch[root][1]) {
		clear(root); root = 0;
		return;
	}
	if(!ch[root][0]) {
		int oldroot = root;
		root = ch[root][1]; p[root] = 0;
		clear(oldroot);
		return;
	} else if(!ch[root][1]) {
		int oldroot = root;
		root = ch[root][0]; p[root] = 0;
		clear(oldroot);
		return;
	}
	int bigleft = pre(), oldroot = root;
	splay(bigleft);
	ch[root][1] = ch[oldroot][1];
	p[ch[root][1]] = root;
	clear(oldroot);
	update(root);
	return;
}

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

*/
int main() {
	int n;
	scanf("%d", &n);
	for(int i = 1; i <= n; i++) {
		int t, x;
		scanf("%d%d", &t, &x);
		switch(t) {
			case 1: insert(x); break;
			case 2: del(x);	break;
			case 3: printf("%d\n", find(x)); break;
			case 4: printf("%d\n", findx(x)); break;
			case 5: insert(x); printf("%d\n", key[pre()]); del(x); break;
			case 6: insert(x); printf("%d\n", key[next()]); del(x); break;
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值