【TYVJ1728】【洛谷P3369】—普通平衡树(Splay写法)
这年头找个好点的板子好难的
还是看的的
操作都是常规的,对着代码看一下就懂了
注意由于的方法比较特殊,需要对前驱后继操作
所以为了保证每次都一定有前驱后继要先加一个极大值和一个极小值
#include<bits/stdc++.h>
using namespace std;
inline int read(){
char ch=getchar();
int res=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
return res*f;
}
const int N=100006;
int n,m,rt,tot;
int fa[N],siz[N],son[N][2],val[N],cnt[N];
#define lc(u) (son[u][0])
#define rc(u) (son[u][1])
inline void pushup(int u){
siz[u]=siz[lc(u)]+siz[rc(u)]+cnt[u];
}
inline void rotate(int v){
int u=fa[v],z=fa[u];
int t=(rc(u)==v);
son[z][rc(z)==u]=v;
fa[v]=z;
son[u][t]=son[v][t^1];
fa[son[v][t^1]]=u;
fa[u]=v,son[v][t^1]=u;
pushup(u),pushup(v);
}
inline void splay(int v,int goal){
while(fa[v]!=goal){
int u=fa[v],z=fa[u];
if(z!=goal)
(lc(z)==u)^(lc(u)==v)?rotate(v):rotate(u);
rotate(v);
}
if(goal==0)rt=v;
}
inline void insert(int x){
int u=rt,f=0;
while(u&&val[u]!=x){
f=u,u=son[u][x>val[u]];
}
if(u)cnt[u]++;
else{
u=++tot;
if(f)son[f][x>val[f]]=u;
lc(u)=rc(u)=0;
fa[u]=f,val[u]=x,siz[u]=cnt[u]=1;
}
splay(u,0);
}
inline void find(int x){
int u=rt;
if(!u)return;
while(son[u][x>val[u]]&&val[u]!=x)
u=son[u][x>val[u]];
splay(u,0);
}
inline int pre(int x){
find(x);
int u=rt;
if(val[u]<x)return u;
u=lc(u);
while(rc(u))u=rc(u);
return u;
}
inline int nxt(int x){
find(x);
int u=rt;
if(val[u]>x)return u;
u=rc(u);
while(lc(u))u=lc(u);
return u;
}
inline void delet(int x){
int last=pre(x),next=nxt(x);
splay(last,0),splay(next,last);
int del=lc(next);
if(cnt[del]>1)cnt[del]--,splay(del,0);
else lc(next)=0;
}
inline int kth(int x){
int u=rt;
if(siz[u]<x)return 0;
while(1){
int y=lc(u);
if(x>siz[y]+cnt[u]){
x-=siz[y]+cnt[u];
u=rc(u);
}
else {
if(x<=siz[y]){
u=y;
}
else return val[u];
}
}
}
int main(){
n=read();
insert(20030224);
insert(-20030224);
for(int i=1;i<=n;i++){
int op=read(),x=read();
switch(op){
case 1:{
insert(x);
break;
}
case 2:{
delet(x);
break;
}
case 3:{
find(x);
cout<<siz[lc(rt)]<<'\n';
break;
}
case 4:{
cout<<kth(x+1)<<'\n';
break;
}
case 5:{
cout<<val[pre(x)]<<'\n';
break;
}
case 6:{
cout<<val[nxt(x)]<<'\n';
break;
}
}
}
}