Treap,替罪羊树,splay。跑得不慢,代码在不影响版面的前提下基本已经缩到极限了,不知道还能不能更短。
其实我还会写AVL树,只不过太长懒得写了。反正Treap和替罪羊树跑得也挺快,用用这俩就够了。
话说Treap和替罪羊树都是重量平衡树来着……这倒是方便我了,不过写动态标号的时候到底该写哪个呢……这是个问题……
Treap(普通平衡树):
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 struct node{ 6 static inline int randint(){ 7 static int a=1213857,b=123542441,x=741542853,p=998244353; 8 x=a*x+b;x%=p; 9 return (x<0)?(x+=p):x; 10 } 11 int data,size,p; 12 node *ch[2]; 13 node(int d):data(d),size(1),p(randint()){} 14 void refresh(){size=ch[0]->size+ch[1]->size+1;} 15 int cmp(int x){return x==data?-1:x>data;} 16 }*null=new node(-1),*root=null; 17 void insert(int,node*&); 18 void erase(int,node*&); 19 int order(int,node*); 20 node *kth(int,node*); 21 node *pred(int,node*); 22 node *succ(int,node*); 23 void rot(node*&,int); 24 int n,d,x; 25 int main(){ 26 null->size=0; 27 null->ch[0]=null->ch[1]=null; 28 scanf("%d",&n); 29 while(n--){ 30 scanf("%d%d",&d,&x); 31 if(d==1)insert(x,root); 32 else if(d==2)erase(x,root); 33 else if(d==3)printf("%d\n",order(x,root)); 34 else if(d==4)printf("%d\n",kth(x,root)->data); 35 else if(d==5)printf("%d\n",pred(x,root)->data); 36 else printf("%d\n",succ(x,root)->data); 37 } 38 return 0; 39 } 40 void insert(int x,node *&rt){ 41 if(rt==null){ 42 rt=new node(x); 43 rt->ch[0]=rt->ch[1]=null; 44 return; 45 } 46 int d=abs(rt->cmp(x)); 47 insert(x,rt->ch[d]); 48 rt->refresh(); 49 if(rt->ch[d]->p<rt->p)rot(rt,d^1); 50 } 51 void erase(int x,node *&rt){ 52 int d=rt->cmp(x); 53 if(d==-1){ 54 if(rt->ch[0]!=null&&rt->ch[1]!=null){ 55 d=rt->ch[0]->p<=rt->ch[1]->p; 56 rot(rt,d); 57 erase(x,rt->ch[d]); 58 } 59 else{ 60 node *y=rt->ch[0]!=null?rt->ch[0]:rt->ch[1]; 61 delete rt; 62 rt=y; 63 } 64 } 65 else erase(x,rt->ch[d]); 66 if(rt!=null)rt->refresh(); 67 } 68 int order(int x,node *rt){ 69 int ans=1,d; 70 while(rt!=null){ 71 if((d=x>rt->data))ans+=rt->ch[0]->size+1; 72 rt=rt->ch[d]; 73 } 74 return ans; 75 } 76 node *kth(int k,node *rt){ 77 int d; 78 while(rt!=null){ 79 if(k==rt->ch[0]->size+1)return rt; 80 if((d=k>rt->ch[0]->size+1))k-=rt->ch[0]->size+1; 81 rt=rt->ch[d]; 82 } 83 return null; 84 } 85 node *pred(int x,node *rt){ 86 node *y=null; 87 int d; 88 while(rt!=null){ 89 if((d=x>rt->data))y=rt; 90 rt=rt->ch[d]; 91 } 92 return y; 93 } 94 node *succ(int x,node *rt){ 95 node *y=null; 96 int d; 97 while(rt!=null){ 98 if((d=x<rt->data))y=rt; 99 rt=rt->ch[d^1]; 100 } 101 return y; 102 } 103 void rot(node *&x,int d){ 104 node *y=x->ch[d^1]; 105 x->ch[d^1]=y->ch[d]; 106 y->ch[d]=x; 107 x->refresh(); 108 (x=y)->refresh(); 109 }