Splay :
其实是个十分神奇的东西——
具体来说呢,就是二叉搜索树的优化,使得它的最坏情况(一条链)消除
再具体一点呢。。。百度百科
这里推荐
yyb神犇的博客
,因为笔者觉得他的博客是我见过博客中写的比较清晰的,常数也是很小的,且笔者也是在他博客中弄懂
Splay
的,希望大家能够有所收获。
Tips:完整代码可以在我这篇文章里看,还有打完板子之后可以在这里评测。
在此附上完整代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<string>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<stack>
#include<algorithm>
#define RG register
#define file(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
using namespace std;
inline int gi(){
int data=0,w=1;
char ch=0;
while(ch!='-'&&(ch>'9'||ch<'0')) ch=getchar();
if(ch=='-') w=-1,ch=getchar();
while(ch>='0'&&ch<='9') data=data*10+ch-'0',ch=getchar();
return data*w;
}
#define N 500010
int root,total;
struct node{
int ch[2],cnt,size,fa,val;
}t[N];
int get(int x){
return t[t[x].fa].ch[1]==x;
}
void pushup(int x){
t[x].size=t[t[x].ch[0]].size+t[t[x].ch[1]].size+t[x].cnt;
}
void rotate(int x){
int y=t[x].fa;int z=t[y].fa;
int which=get(x);
t[z].ch[get(y)]=x;
t[x].fa=z;
t[y].ch[which]=t[x].ch[which^1];
t[t[x].ch[which^1]].fa=y;
t[x].ch[which^1]=y;
t[y].fa=x;
pushup(y);pushup(x);
}
void splay(int x,int goal){
while(t[x].fa!=goal){
int y=t[x].fa,z=t[y].fa;
if(z!=goal)
get(x)^get(y)?rotate(x):rotate(y);
rotate(x);
}
if(goal==0) root=x;
}
inline void find(int x){
int u=root;
if(!u) return ;
while(t[u].ch[x>t[u].val]&&x!=t[u].val) {
u=t[u].ch[x>t[u].val];
}
splay(u,0);
}
void insert(int x){
int u=root,fa=0;
while(u&&t[u].val!=x){
fa=u;
u=t[u].ch[x>t[u].val];
}
if(u) t[u].cnt++;
else{
total++;
u=total;
if(fa) t[fa].ch[x>t[fa].val]=u;
t[u].ch[0]=t[u].ch[1]=0;
t[total].fa=fa;
t[total].val=x;
t[total].cnt=1;
t[total].size=1;
}
splay(u,0);
}
int NEXT(int x,int f){
find(x);
int u=root;
if(t[u].val>x&&f) return u;
if(t[u].val<x&&!f) return u;
u=t[u].ch[f];
while(t[u].ch[f^1]) u=t[u].ch[f^1];
return u;
}
void Delete(int x){
int last=NEXT(x,0);
int next=NEXT(x,1);
splay(last,0);splay(next,last);
int del=t[next].ch[0];
if(t[del].cnt>1){
t[del].cnt--;
splay(del,0);
}
else t[next].ch[0]=0;
}
int Rank(int x){
int u=root;
if(t[u].size<x) return 0;
while(true){
int y=t[u].ch[0];
if(x>t[y].size+t[u].cnt){
x-=t[y].size+t[u].cnt;
u=t[u].ch[1];
}
else if(t[y].size>=x) u=y;
else return t[u].val;
}
}
int main(){
RG int n=gi();
insert( 2147483647);
insert(-2147483647);
while(n--){
int opt=gi();
if(opt==1){insert(gi());}
if(opt==2){Delete(gi());}
if(opt==3){find(gi());printf("%d\n",t[t[root].ch[0]].size);}
if(opt==4){printf("%d\n",Rank(gi()+1));}
if(opt==5){printf("%d\n",t[NEXT(gi(),0)].val);}
if(opt==6){printf("%d\n",t[NEXT(gi(),1)].val);}
}
return 0;
}