1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #define ls(x) (x->ch[0]) 5 #define rs(x) (x->ch[1]) 6 #define sz(x) (x->size) 7 #define p(x) (x->p) 8 using namespace std; 9 const int INF=0x7fffffff; 10 struct son 11 { 12 int v,size; 13 son *ch[2],*p; 14 son(int x) 15 { 16 v=x;size=1; 17 } 18 }; 19 son *root,*null; 20 son* newson(int val) 21 { 22 son *x=new son(val); 23 ls(x)=rs(x)=p(x)=null; 24 return x; 25 } 26 void pushup(son *x){sz(x)=sz(ls(x))+sz(rs(x))+1;} 27 int rank(int val) 28 { 29 son *x=root; 30 int ans=0; 31 while(x!=null) 32 { 33 if(val>x->v){ans+=(sz(ls(x))+1);x=rs(x);} 34 else x=ls(x); 35 } 36 return ans; 37 } 38 son* kth(int k) 39 { 40 //printf("sha bi qin shi yu\n"); 41 son *x=root; 42 while(x!=null) 43 { 44 if(sz(ls(x))+1==k)return x; 45 if(sz(ls(x))+1>k)x=ls(x); 46 else {k-=(sz(ls(x))+1);x=rs(x);} 47 } 48 return null; 49 } 50 int islc(son *x){return ls(p(x))==x;} 51 // is left child ??? 52 //x在右,就左旋 在左,就右旋 53 void rot(son *x,int d) 54 { 55 son *y=x->ch[d^1]; 56 if(p(x)!=null)p(x)->ch[islc(x)^1]=y;//祖父儿子=y 57 else root=y; 58 p(y)=p(x);//把祖父儿子设成y 59 x->ch[d^1]=y->ch[d];// 60 if(y->ch[d])p(y->ch[d])=x;//把y的d同向儿子改成x的d逆向儿子 61 y->ch[d]=x;p(x)=y;//把x的爸爸改成y 62 pushup(x);pushup(y); 63 } 64 void splay(son *x,son *t=null)//把x旋到以t为祖父节点 65 { 66 for(son *rt=p(x);rt!=t;rt=p(x)) 67 { 68 if(p(rt)==t) 69 { 70 rot(rt,islc(x)); 71 return ; 72 } 73 if(islc(x)==islc(rt))rot(p(rt),islc(rt));//一字型旋转 第一步 74 else rot(rt,islc(x));//之字形旋转 第一步 75 rot(p(x),islc(x));//第二步 (此时x已经转上去) 76 } 77 } 78 void add(int val) 79 { 80 int pos=rank(val);//val排名-1 81 splay(kth(pos));//把前一个转到root 82 splay(kth(pos+1),root);//把pos+1的转到root右儿子 83 //val 卡在pos和pos+1之间 84 son *x=newson(val); 85 root->ch[1]->ch[0]=x; 86 p(x)=root->ch[1]; 87 pushup(root->ch[1]);pushup(root); 88 } 89 void del(int val) 90 { 91 int pos=rank(val)+1; 92 splay(kth(pos-1));splay(kth(pos+1),root); 93 //把val卡在pos-1和pos+1之间 94 root->ch[1]->ch[0]=null; 95 pushup(root->ch[1]);pushup(root); 96 } 97 int n; 98 99 int main(){ 100 //freopen("phs.in","r",stdin); 101 //freopen("phs.out","w",stdout); 102 null=new son(0);sz(null)=0; 103 root=newson(-INF); 104 root->ch[1]=newson(INF);//即把一开始的区间调成-INF到INF 105 p(root->ch[1])=root; 106 scanf("%d",&n); 107 for(int i=1;i<=n;++i) 108 { 109 int opt,x;scanf("%d%d",&opt,&x); 110 switch(opt) 111 { 112 case 1:add(x);break; 113 case 2:del(x);break; 114 case 3:printf("%d\n",rank(x));break; 115 //返回值就是rank的原因:******** 116 //一开始root的值=-INF root右儿子=INF ******* 117 //每次查找一定会到这两个节点,而他们size=1 118 case 4:printf("%d\n",kth(x+1)->v);break; 119 //不能轻易在rank上+1,必须在x上+1 120 case 5:printf("%d\n",kth(rank(x))->v);break; 121 case 6:printf("%d\n",kth(rank(x+1)+1)->v);break; 122 } 123 } 124 while(1); 125 return 0; 126 }
Splay详细注释
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #define ls(x) (x->l) 6 #define rs(x) (x->r) 7 #define sz(x) ((x)?(x->size):(0)) 8 using namespace std; 9 struct Treap 10 { 11 struct treap 12 { 13 int size,fix,val; 14 treap *l,*r; 15 treap(int x) 16 { 17 val=x;fix=rand();size=1; 18 l=r=NULL; 19 } 20 }*root; 21 void pushup(treap *x){x->size=sz(ls(x))+sz(rs(x))+1;} 22 void lturn(treap *&x) 23 { 24 treap *y=rs(x); 25 rs(x)=ls(y);pushup(x); 26 ls(y)=x;pushup(y); 27 x=y; 28 } 29 void rturn(treap *&x) 30 { 31 treap *y=ls(x); 32 ls(x)=rs(y);pushup(x); 33 rs(y)=x;pushup(y); 34 x=y; 35 } 36 void add(treap *&x,int val) 37 { 38 if(x==NULL) 39 { 40 x=new treap(val); 41 return ; 42 } 43 if(val<x->val) 44 { 45 add(ls(x),val); 46 pushup(x); 47 if(ls(x)->fix>x->fix)rturn(x); 48 } 49 else 50 { 51 add(rs(x),val); 52 pushup(x); 53 if(rs(x)->fix>x->fix)lturn(x); 54 } 55 } 56 void del(treap *&x,int val) 57 { 58 if(val==x->val) 59 { 60 if(ls(x)&&rs(x)) 61 { 62 if(ls(x)->fix>rs(x)->fix){rturn(x);del(rs(x),val);} 63 else {lturn(x);del(ls(x),val);} 64 } 65 else 66 { 67 treap *y=NULL; 68 if(ls(x))y=ls(x); 69 else y=rs(x); 70 delete x;x=y; 71 } 72 } 73 else 74 { 75 if(val<x->val)del(ls(x),val); 76 else del(rs(x),val); 77 } 78 if(x)pushup(x); 79 } 80 int rank(int val) 81 { 82 treap *x=root; 83 int ans=0; 84 while(x) 85 { 86 if(val>x->val){ans+=(sz(ls(x))+1);x=rs(x);} 87 else x=ls(x); 88 } 89 return ans; 90 } 91 treap* kth(int k) 92 { 93 treap *x=root; 94 while(x) 95 { 96 int size=sz(ls(x))+1; 97 if(size==k)return x; 98 if(size>=k)x=ls(x); 99 // = 向右走,因为add的时候就是向右 100 else {k-=size;x=rs(x);} 101 } 102 } 103 }T; 104 105 int m,u,o; 106 107 int main(){ 108 //freopen("phs.in","r",stdin); 109 //freopen("phs.out","w",stdout); 110 scanf("%d",&m); 111 while(m--) 112 { 113 scanf("%d%d",&u,&o); 114 if(u==1)T.add(T.root,o); 115 else if(u==2)T.del(T.root,o); 116 else if(u==3)printf("%d\n",T.rank(o)+1); 117 else if(u==4)printf("%d\n",T.kth(o)->val); 118 else if(u==5)printf("%d\n",T.kth(T.rank(o))->val); 119 else printf("%d\n",T.kth(T.rank(o+1)+1)->val); 120 //加2有可能返回一个空指针,炸掉你 121 } 122 while(1); 123 return 0; 124 }
旋转Treap
时间: 2024-11-07 17:45:51