【CSDN网盘系列】splay模板

本文详细介绍了洛谷平衡树模板题的实现和使用,包括旋转操作、查询与插入删除功能。通过代码解析,展示了如何高效地进行数据操作,并提供了主函数中的各个操作案例,帮助读者理解并掌握平衡树在算法竞赛中的应用。

题目

洛谷平衡树模板题

CODE

调了半天终于第一次调出splay呀!

#include<cstdio>
#include<algorithm>
using namespace std;
struct node {
	int l,r,fa,cnt,size,v;
}f[100005];
int tot,rt,n,x,t;
void maintain(int x) {f[x].size=f[f[x].l].size+f[f[x].r].size+f[x].cnt;}
void clean(int x) {f[x].size=f[x].cnt=f[x].l=f[x].r=f[x].v=f[x].fa=0;}
void xuan(int x) {
	int y=f[x].fa,z=f[y].fa;
	if (x==f[y].r) {f[y].r=f[x].l,f[f[x].l].fa=y,f[x].l=y,f[y].fa=x,f[x].fa=z;}
	else if (x==f[y].l) {f[y].l=f[x].r,f[f[x].r].fa=y,f[x].r=y,f[y].fa=x,f[x].fa=z;}
	if (z) {if (y==f[z].l) f[z].l=x; if (y==f[z].r) f[z].r=x;}
	maintain(y),maintain(x);
}
void splay(int x) {
	for (int i=f[x].fa;i=f[x].fa,i;xuan(x))
		if (f[i].fa)
			if ((x==f[f[x].fa].l&&i==f[f[i].fa].l)||(x==f[f[x].fa].r&&i==f[f[i].fa].r)) xuan(i); else xuan(x);
	rt=x;
}
int qian() {int now=f[rt].l; while (f[now].r) now=f[now].r; splay(now); return now;}
int hou() {int now=f[rt].r; while (f[now].l) now=f[now].l; splay(now); return now;}
int rank(int x) {
	int now=rt,ans=0;
	while (1) {
		if (x<f[now].v) now=f[now].l;
		else if (x>f[now].v) ans+=f[f[now].l].size+f[now].cnt,now=f[now].r;
		else if (x==f[now].v) {ans+=f[f[now].l].size,splay(now); return ans+1;} 
	}
}
int th(int x) {
	int now=rt;
	while (1) {
		if (f[now].l&&x<=f[f[now].l].size) now=f[now].l;
		else {
			x-=(f[f[now].l].size+f[now].cnt);
			if (x<=0) {splay(now); return f[now].v;} now=f[now].r;}
	}
}
void ins(int x) {
	if (!rt) {rt=++tot,f[rt].v=x,f[rt].cnt++,maintain(rt); return;}
	int now=rt,p=0;
	while (1) {
		if (x==f[now].v) {f[now].cnt++,maintain(now),maintain(p),splay(now); break;}
		p=now; if (x>f[now].v) now=f[now].r; else now=f[now].l;
		if (!now) {
			f[++tot].v=x,f[tot].cnt++,f[tot].fa=p;
			if  (x>f[p].v) f[p].r=tot; else f[p].l=tot; maintain(tot),maintain(p),splay(tot); break;}
	}
}
void del(int x) {
	int r=rank(x);
	if (f[rt].cnt>1) {f[rt].cnt--,maintain(rt); return;}
	if (!f[rt].l&&!f[rt].r) {clean(rt),rt=0; return;}
	if (!f[rt].l) {int now=rt; rt=f[rt].r,f[rt].fa=0,clean(now); return;}
	if (!f[rt].r) {int now=rt; rt=f[rt].l,f[rt].fa=0,clean(now); return;}
	int now=rt,xx=qian(); f[f[now].r].fa=xx,f[xx].r=f[now].r,clean(now),maintain(rt);
}
int main() {
	scanf("%d",&n);
	while (n--) {
		scanf("%d%d",&t,&x); if (t==1) ins(x); if (t==2) del(x); if (t==3) printf("%d\n",rank(x)); if (t==4) printf("%d\n",th(x)); 
		if (t==5) ins(x),printf("%d\n",f[qian()].v),del(x); if (t==6) ins(x),printf("%d\n",f[hou()].v),del(x);
	}
}

splay详解看看哪天能补上?

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值