【模板篇】伸展树Splay Tree(此坑待填)
2017-04-04 09:58
309 查看
已填坑: 请移步…
Splay?伸展。
Splay Tree?伸展树。
遇事不决问度娘。。
从前,有种东西叫BST(Binary Search Tree,二叉查找树),各位都听说过吧?
此BST能较为高效的查找数据。。(所以是查找树嘛)
而它却有一个致命的缺点!常常会被卡成一条链。。
不是链的时候树也会很高。。。。效率很难维持住O(nlogn)
所以,人们研究了各种的二叉平衡树,通过对BST各种姿势的调整维护树的左右平衡,使树高不会太高,从而防止效率退化。。
Splay是其中的一种(然而还是会被卡)。。在省选这个阶段似乎是够用了。。
Splay有很多操作,其中最重要的,当然是splay..
Splay在维护信息时,会将各种东西伸展到根上,(扭来扭去的),这也就是splay树名字的由来了吧。。
先把板子丢上来…
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; } } }
相关文章推荐
- Splay Tree(伸展树)
- 伸展树(Splay Tree)
- 二叉查找树,AVL,伸展树(splay tree)c/c++实现
- splay tree(伸展树)详解
- 自平衡树--伸展树(Splay Tree)
- 基本算法连载(2)-Splay Tree,中文叫伸展树,或者分裂树
- 纸上谈兵:伸展树(splay tree)
- 学习总结:Splay Tree 伸展树
- Splay Tree,中文叫伸展树,或者分裂树
- 伸展树splay tree
- 伸展树 Splay Tree
- 伸展树(Splay Tree)尽收眼底
- 伸展树(Splay Tree)
- 伸展树(Splay tree)图解与实现
- 伸展树模板小结(Splay Tree)
- (转)伸展树 ( Splay tree )
- 伸展树(splay tree)实现
- Splay Tree(伸展树)[NOI2005]维修数列
- Splay tree 伸展树 (不含区间操作)模板
- Splay Tree(伸展树)