安利splay讲解:
【模板】普通平衡树(luogu)
Description
题目描述
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
输入格式
第一行为 nn,表示操作的个数,下面 nn 行每行有两个数 \text{opt}opt 和 xx,\text{opt}opt 表示操作的序号( 1 \leq \text{opt} \leq 61≤opt≤6 )
输出格式
对于操作 3,4,5,63,4,5,6 每行输出一个数,表示对应答案
Code
#include <iostream>
using namespace std;
const int N=1e5+10;
//1:插入xx数
//2:删除xx数(若有多个相同的数,因只删除一个)
//3:查询xx数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)
//4:查询排名为xx的数
//5:求xx的前驱(前驱定义为小于xx,且最大的数)
//6:求xx的后继(后继定义为大于xx,且最小的数)
int n,x,opt,cnt[N],size[N],val[N],tot,ch[N][2],rt,fa[N];
struct Splay
{
void push_up(int x)
{
size[x]=size[ch[x][0]]+size[ch[x][1]]+cnt[x];
}
bool get(int x)
{
return x==ch[fa[x]][1];
}
void clear(int x)
{
size[x]=ch[x][0]=ch[x][1]=cnt[x]=val[x]=fa[x]=0;
}
void rotate(int x)
{
int y=fa[x],z=fa[y],wh=get(x);
fa[ch[x][wh^1]]=y;
ch[y][wh]=ch[x][wh^1];
ch[x][wh^1]=y;
fa[x]=z,fa[y]=x;
if(z) ch[z][y==ch[z][1]]=x;
push_up(y),push_up(x);
}
void splay(int x)
{
for(int f=fa[x];f=fa[x],f;rotate(x))
if(fa[f]) rotate(get(f)==get(x)?f:x);
rt=x;
}
int nxt()
{
int now=ch[rt][1];
while(ch[now][0]) now=ch[now][0];
return now;
}
int pre()
{
int now=ch[rt][0];
while(ch[now][1]) now=ch[now][1];
return now;
}
int rk(int x)
{
int res=0,now=rt;
while(1)
{
if(x<val[now]) now=ch[now][0];
else
{
res+=size[ch[now][0]];
if(x==val[now])
{
splay(now);
return res+1;
}
res+=cnt[now],now=ch[now][1];
}
}
}
int kth(int x)
{
int now=rt;
while(1)
{
if(ch[now][0] && x<=size[ch[now][0]]) now=ch[now][0];
else
{
x-=size[ch[now][0]]+cnt[now];
if(x<=0) return val[now];
now=ch[now][1];
}
}
}
void ins(int x)
{
if(!rt)
{
rt=++tot,cnt[tot]=1,val[tot]=x;
push_up(tot);
return ;
}
int now=rt,par=0;
while(1)
{
if(val[now]==x)
{
cnt[now]++;
push_up(now),push_up(par);
splay(now);
return ;
}
par=now,now=ch[now][x>val[now]];
if(!now)
{
cnt[++tot]=1,val[tot]=x,fa[tot]=par;
ch[par][x>val[par]]=tot;
push_up(tot),push_up(par);
splay(tot);
return ;
}
}
}
void del(int x)
{
rk(x);
if(cnt[rt]>1) cnt[rt]--,push_up(rt);
else if(!ch[rt][0] && !ch[rt][1]) clear(rt),rt=0;
else if(!ch[rt][0])
{
int now=rt;
rt=ch[rt][1],fa[rt]=0;
clear(now);
}
else if(!ch[rt][1])
{
int now=rt;
rt=ch[rt][0],fa[rt]=0;
clear(now);
}
else
{
int x=pre(),now=rt;
splay(x);
fa[ch[now][1]]=rt;
ch[rt][1]=ch[now][1];
clear(now);
push_up(rt);
}
}
}tree;
int main()
{
ios::sync_with_stdio(false);
cin>>n;
while(n--)
{
cin>>opt>>x;
if(opt==1) tree.ins(x);
else if(opt==2) tree.del(x);
else if(opt==3) cout<<tree.rk(x)<<endl;
else if(opt==4) cout<<tree.kth(x)<<endl;
else if(opt==5) tree.ins(x),cout<<val[tree.pre()]<<endl,tree.del(x);
else if(opt==6) tree.ins(x),cout<<val[tree.nxt()]<<endl,tree.del(x);
}
return 0;
}
原文:https://www.cnblogs.com/hsez-cyx/p/12244736.html