[BZOJ3224]普通平衡树 SPlay

诶一个中午种了两棵树

写平衡树之前一定要明确数组的定义,想好每个过程怎么写之后再开始动手写

想清楚每个操作返回的是结点的编号还是结点的值

诶又是wall编译救了我


#include <iostream>
#include <cstdio>
#define INF 1<<30
#define N 200050
using namespace std;
int tr[N],siz[N],fa[N],s[N][2];
int cur[N],cnt,rt;

inline void update(int t) { siz[t] = siz[ s[t][0] ] + siz[ s[t][1] ] + cur[t]; }
void rot(int x,int &k) {
	int y = fa[x] , z = fa[y] , l = (s[y][0] == x) ^ 1 , r = l ^ 1;
	if (y == k) k = x; else { if (s[z][0] == y) s[z][0] = x; else s[z][1] = x; }
	s[y][l] = s[x][r]; s[x][r] = y;
	fa[x] = z; fa[y] = x; fa[ s[y][l] ] = y;
	update(y); update(x);
}

void SPlay(int x,int &k) {
	while (x != k) {
		int y = fa[x] , z = fa[y];
		if (y != k) { if ((s[z][0] == y) ^ (s[y][0] == x)) rot(x,k); else rot(y,k); }
		rot(x,k);
	}
}

int qf(int x,int t) {
	if (!t) return 0;
	if (tr[t] < x) { int tmp = qf(x,s[t][1]); return tmp ? tmp : t; }
	else return qf(x,s[t][0]);
}

int qa(int x,int t) {
	if (!t) return 0;
	if (tr[t] > x) { int tmp = qa(x,s[t][0]); return tmp ? tmp : t; }
	else return qa(x,s[t][1]);
}

int query(int x,int t) {
	if (x == tr[t]) return siz[ s[t][0] ] + 1;
	return (x < tr[t]) ? query(x,s[t][0]) : siz[ s[t][0] ] + cur[t] + query(x,s[t][1]);
}

int kth(int k,int t) {
	int ll = siz[ s[t][0] ] + 1 , rr = siz[ s[t][0] ] + cur[t];
	if (ll <= k && k <= rr) return t;
	return (k > rr) ? kth(k-rr,s[t][1]) : kth(k,s[t][0]);
}

void ins(int x,int &t,int f) {
	if (!t) { tr[ t=++cnt ] = x; siz[t] = 1; fa[t] = f; cur[t] = 1; return ; }
	if (x == tr[t]) { cur[t]++; siz[t]++; return ; }
	if (x < tr[t]) ins(x,s[t][0],t); else ins(x,s[t][1],t);
	update(t);
}

void del(int x,int &t) {
	int u = qf(x,rt) , v = qa(x,rt);
	SPlay(v,rt); SPlay(u,s[v][0]);
	int c = s[u][1];
	if (cur[c]-1) {
		cur[c]-- , SPlay(c,rt);
	} else { 
		tr[c] = 0; siz[c] = 0; fa[c] = 0; s[u][1] = 0;
	}
	update(u); update(v);
}
inline void koo(int t) { printf("%d\n",tr[t]); SPlay(t,rt); }
int main()
{
	#ifndef ONLINE_JUDGE
		freopen("input.in","r",stdin);
		freopen("input.out","w",stdout);
	#endif
	int n = 0; scanf("%d",&n);
	ins(-INF,rt,0); SPlay(cnt,rt);
	ins( INF,rt,0); SPlay(cnt,rt);
	while (n--) {
		int cmd = 0 , x = 0;
		scanf("%d%d",&cmd,&x);
		switch(cmd) {
			case 1:{ ins(x,rt,0); SPlay(cnt,rt); break; }
			case 2:{ del(x,rt); break; }
			case 3:{ printf("%d\n",query(x,rt)-1); break; }
			case 4:{ int t = kth(x+1,rt); koo(t); break; }
			case 5:{ int t = qf(x,rt);    koo(t); break; }
			case 6:{ int t = qa(x,rt);    koo(t); break; }
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值