其实平衡树这个东东,我原来也是打过那么几遍的,而且三种基本的都打过了。但是呢,当时内心抵触指针,于是就用的网上的数组平衡树模板
理解起来倒是没什么问题,无奈码量略大T_T
然后就有一段时间没打平衡树了。这两天刷数据结构专题,发现一道 [HNOI 2012]永无乡 需要建多颗平衡树。
我靠!这是对我的数组平衡树的毁灭性的打击啊!!
于是狠了狠心,学指针打法!
然后hww神牛为我提供了他的板子。照着打了不到一个小时,发现指针实现的话,码量灰常小的,而且也很好理解的!
于是乎我现在满心欢喜。不过悲催的是我的splay还是用数组实现的T_T。找个机会把splay也改成指针打法。
嗯。先把Treap搞定了。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; #define pos(i,a,b) for(int i=(a);i<=(b);i++) #define N 101000 #include<cstdlib> #define size(x) ((x)?(x->size):(0)) #define ls(x) (x->ch[0]) #define rs(x) (x->ch[1]) int n; struct Treap{ int size,v,key; Treap *ch[2]; Treap(int x=0){ v=x;size=1;key=rand();ch[0]=ch[1]=NULL; } }*root; void pushup(Treap *rt){ rt->size=size(ls(rt))+size(rs(rt))+1; } void turn(Treap *&rt,int d){ Treap *t=rt->ch[d^1]; rt->ch[d^1]=t->ch[d];pushup(rt); t->ch[d]=rt;pushup(t); rt=t; } void insert(Treap *&rt,int x){ if(!rt){ rt=new Treap(x);return; } int d=x < rt->v; insert(rt->ch[d^1],x); pushup(rt); if(rt->ch[d^1]->key < rt->key) turn(rt,d); } void del(Treap *&rt,int x){ if(rt->v==x){ if(ls(rt)&&rs(rt)){ int d=ls(rt)->key < rs(rt)->key; turn(rt,d);del(rt->ch[d],x); } else{ Treap *t=NULL; if(ls(rt)) t=ls(rt); else t=rs(rt); delete rt;rt=t; } } else{ int d=x < rt->v; del(rt->ch[d^1],x); } if(rt) pushup(rt); } int Rank(int x){ Treap *rt=root; int ans(0); while(rt){ if(x > rt->v){ ans+=size(ls(rt))+1; rt=rs(rt); } else rt=ls(rt); } return ans; } int kth(int k){ Treap *rt=root; while(rt){ if(size(ls(rt))+1==k) return rt->v; if(size(ls(rt))+1>k) rt=ls(rt); else{ k-=size(ls(rt))+1;rt=rs(rt); } } return 0; } int main(){ scanf("%d",&n); pos(i,1,n){ int opt,x; scanf("%d%d",&opt,&x); if(opt==1) insert(root,x); else if(opt==2) del(root,x); else if(opt==3) printf("%d\n",Rank(x)+1); else if(opt==4) printf("%d\n",kth(x)); else if(opt==5) printf("%d\n",kth(Rank(x))); else if(opt==6) printf("%d\n",kth(Rank(x+1)+1)); } return 0; }
时间: 2024-10-25 07:22:03