已填坑: 请移步…
Splay?伸展。
Splay Tree?伸展树。
遇事不决问度娘。。
从前,有种东西叫BST(Binary Search Tree,二叉查找树),各位都听说过吧?
此BST能较为高效的查找数据。。(所以是查找树嘛)
而它却有一个致命的缺点!常常会被卡成一条链。。
不是链的时候树也会很高。。。。效率很难维持住O(nlogn)
所以,人们研究了各种的二叉平衡树,通过对BST各种姿势的调整维护树的左右平衡,使树高不会太高,从而防止效率退化。。
Splay是其中的一种(然而还是会被卡)。。在省选这个阶段似乎是够用了。。
Splay有很多操作,其中最重要的,当然是splay..
Splay在维护信息时,会将各种东西伸展到根上,(扭来扭去的),这也就是splay树名字的由来了吧。。
先把板子丢上来…
#include <cstdio>
const int MAXQ=0x186AF;
const int INF=~0U>>2;
#define gc getchar()
#define xx(x) printf("%d\n",x)
inline int gnum(){
int a=0;char c=gc;bool f=0;
for(;(c<'0'||c>'9')&&c!='-';c=gc);
if(c=='-') c=gc,f=1;
for(;c>='0'&&c<='9';c=gc) a=(a<<1)+(a<<3)+c-'0';
if(f) return -a; return a;
}
inline int max(const int &a,const int &b){
if(a<b) return b; return a;
}
inline int min(const int &a,const int &b){
if(a<b) return a; return b;
}
struct SPLAY{
int val,sz,cnt;
SPLAY *fa,*ch[2];
void update();
int get_wh();
void set_ch(int,SPLAY*);
}pool[MAXQ],*rt,*null;
void SPLAY::update(){
sz=ch[0]->sz+ch[1]->sz+cnt;
}
int SPLAY::get_wh(){
return fa->ch[0]==this?0:1;
}
void SPLAY::set_ch(int wh,SPLAY *child){
ch[wh]=child;
if(child!=null) child->fa=this;
update();
}
int tot=0;
inline SPLAY* NEW(int val){
SPLAY *now=pool+ ++tot;
now->val=val;
now->sz=now->cnt=1;
now->fa=now->ch[0]=now->ch[1]=null;
return now;
}
void init(){
null=pool;
null->val=null->sz=null->cnt=0;
null->fa=null->ch[0]=null->ch[1]=null;
rt=null;
}
inline void rotate(SPLAY *&now){
SPLAY *fa=now->fa,*fafa=now->fa->fa;
int wh=now->get_wh(),fwh=fa->get_wh();
fa->set_ch(wh,now->ch[wh^1]);
now->set_ch(wh^1,fa);
now->fa=fafa;
if(fafa!=null)
fafa->ch[fwh]=now;
}
inline void splay(SPLAY *now,SPLAY *tar){
for(;now->fa!=tar;rotate(now))
if(now->fa->fa!=tar)
now->get_wh()==now->fa->get_wh()?rotate(now->fa):rotate(now);
if(tar==null) rt=now;
}
inline SPLAY* find(int val){
SPLAY *now=rt;
while(now!=null){
if(now->val==val) break;
if(now->val>val) now=now->ch[0];
else now=now->ch[1];
}
if(now!=null) splay(now,null);
return now;
}
void ins(int val){
SPLAY *last=null,*now=rt,*nnow=NEW(val);
while(now!=null){
last=now;
if(nnow->val==now->val){
now->cnt++; now->sz++;
splay(now,null); return;
}
if(nnow->val<now->val) now=now->ch[0];
else now=now->ch[1];
}
if(last==now) rt=nnow;
else if(nnow->val<last->val) last->set_ch(0,nnow);
else last->set_ch(1,nnow);
splay(nnow,null);
}
void del(int val){
SPLAY *now=find(val);
if(now==null) return;
if(now->cnt>1){
now->sz--; now->cnt--; return;
}
if(now->ch[0]==null&&now->ch[1]==null) rt=null;
else if(now->ch[1]==null)
now->ch[0]->fa=null,rt=now->ch[0];
else if(now->ch[0]==null)
now->ch[1]->fa=null,rt=now->ch[1];
else{
SPLAY *ch=now->ch[0];
while(ch->ch[1]!=null) ch=ch->ch[1];
splay(ch,now);
ch->set_ch(1,now->ch[1]);
ch->fa=null;
rt=ch;
}
}
inline int pre(int val){
int ans=-INF;
SPLAY *now=rt;
while(now!=null)
if(now->val<val)
ans=max(ans,now->val),now=now->ch[1];
else now=now->ch[0];
return ans;
}
inline int nxt(int val){
int ans=INF;
SPLAY *now=rt;
while(now!=null)
if(now->val>val)
ans=min(ans,now->val),now=now->ch[0];
else now=now->ch[1];
return ans;
}
inline int rnk(int val){
SPLAY *now=rt;
int ls=0;
while(now!=null){
if(val==now->val){
int ans=ls+now->ch[0]->sz+1;
splay(now,null);
return ans;
}
if(val<now->val) now=now->ch[0];
else ls+=now->cnt+now->ch[0]->sz,now=now->ch[1];
}
return -1;
}
//inline int rnk(int val){
// SPLAY *now=rt;
// int ls=0;
// while(now!=null){
// if(val==now->val){
// int ans=ls+now->ch[0]->sz+1;
// splay(now,null);
// return ans;
// }
// if(val<now->val) now=now->ch[0];
// else ls+=now->ch[0]->sz+now->cnt,now=now->ch[1];
// }
// return -1;
//}
inline int pos(int k){
SPLAY *now=rt;
int ls=0;
while(now!=null){
int x=ls+now->ch[0]->sz;
if(x+1<=k&&k<=x+now->cnt){
splay(now,null);
return now->val;
}
if(k<=x) now=now->ch[0];
else ls=x+now->cnt,now=now->ch[1];
}
return -1;
}
int main(){
int n=gnum(); init();
for(int i=1;i<=n;i++){
int opt=gnum(),x=gnum();
switch(opt){
case 1:ins(x);break;
case 2:del(x);break;
case 3:xx(rnk(x));break;
case 4:xx(pos(x));break;
case 5:xx(pre(x));break;
case 6:xx(nxt(x));break;
}
}
}