Splay板子
本代码由张大仙独家冠名
从张大仙那里翻译而来。原链接大仙的Splay超详细讲解!学Splay这一篇就够了!
代码如下:
#include <bits/stdc++.h>
using namespace std;
const int maxn=100000+10,Inf=0x3f3f3f3f;
int ch[maxn][2],cnt[maxn],size[maxn],val[maxn],fa[maxn];
int root,tot,n,m;
void update(int x){
size[x]=size[ch[x][0]]+size[ch[x][1]]+cnt[x];
}
void rotate(int x){
int y=fa[x],z=fa[y],k=(ch[y][1]==x) ;
ch[z][ch[z][1]==y] = x;
fa[x]=z;
ch[y][k]=ch[x][!k];
fa[ch[x][!k]]=y;
ch[x][!k]=y;
fa[y]=x;
update(y);
update(x);
}
void Splay(int x,int t){
while(fa[x]!=t){
int y=fa[x],z=fa[y];
if(z!=t) (ch[y][0]==x)^(ch[z][0]==y) ? rotate(y) : rotate(x) ;
rotate(x);
}
if(!t) root=x;
}
void find(int x){
int u=root;
while(ch[u][x>val[u]]&&x!=val[u]) u=ch[u][x>val[u]];
Splay(u,0);
}
void Insert(int x){
int u=root,f=0;
while(u && x!=val[u]){
f=u;
u=ch[u][x>val[u]];
}
if(u) cnt[u]++;
else{
u=++tot;
if(f) ch[f][x>val[f]] = u;
val[u]=x;
fa[u]=f;
cnt[u]=size[u]=1;
}
Splay(u,0);
}
int pre(int x){
find(x);
if(x>val[root]) return root;
int u=ch[root][0];
if(!u) return -1;
while(ch[u][1]) u=ch[u][1];
return u;
}
int next(int x){
find(x);
if(x<val[root]) return root;
int u=ch[root][1];
if(!u) return -1;
while(ch[u][0]) u=ch[u][0];
return u;
}
void Delete(int x){
int xp=pre(x),xn=next(x);
Splay(xp,0);
Splay(xn,root);
int u=ch[xn][0];
if(cnt[u]>1){
cnt[u]--;
Splay(u,0);
}
else{
ch[xn][0]=0;
update(xp);
update(xn);
}
}
int kth(int x){
int u=root;
if(size[u]<x) return -1;
while(1){
if(x<=size[ch[u][0]]) u=ch[u][0];
else if(x>size[ch[u][0]]+cnt[u]){
x-=size[ch[u][0]]+cnt[u];
u=ch[u][1];
}
else return u;
}
}
int rank(int x){
find(x);
return size[ch[root][0]];
}
void Solve(){
scanf("%d",&n);
Insert(-Inf);Insert(Inf);
for(int i=1,op,x;i<=n;++i){
scanf("%d%d",&op,&x);
if(op==1) Insert(x);
else if(op==2) Delete(x);
else if(op==3) printf("%d\n",rank(x));
else if(op==4) printf("%d\n",val[kth(x+1)]);
else if(op==5) printf("%d\n",val[pre(x)]);
else printf("%d\n",val[next(x)]);
}
}
int main(){
Solve();
return 0;
}