您的位置:首页 > 其它

【模板篇】伸展树Splay Tree(此坑待填)

2017-04-04 09:58 309 查看
已填坑: 请移步…

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;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: