[luogu P3369]【模板】普通平衡树(Treap/SBT)
题目描述
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
-
插入x数
-
删除x数(若有多个相同的数,因只删除一个)
-
查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)
-
查询排名为x的数
-
求x的前驱(前驱定义为小于x,且最大的数)
- 求x的后继(后继定义为大于x,且最小的数)
输入输出格式
输入格式:
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号( 1 \leq opt \leq 61≤opt≤6 )
输出格式:
对于操作3,4,5,6每行输出一个数,表示对应答案
输入输出样例
输入样例#1: 复制
10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
输出样例#1: 复制
106465
84185
492737
说明
时空限制:1000ms,128M
1.n的数据范围: n \leq 100000n≤100000
2.每个数的数据范围: [-{10}^7, {10}^7][−107,107]
来源:Tyvj1728 原名:普通平衡树
在此鸣谢
用一下午的时间打了一发treap(第一次打),感觉还挺好,实现起来没有其他平衡树高。。
然后。。主要是操作方便,旋转容易(主要依赖于树堆性质和随机期望)。。
不说了,直接贴板子。。
code:
View Code
再来一发链表指针版的(据说写大数据结构链表很常用)——
code:
1 %:pragma GCC optimize(2) 2 #include<bits/stdc++.h> 3 using namespace std; 4 int ans; 5 class tnode{ 6 private: 7 int v,c,k,s; tnode *ch[2]; 8 public: 9 tnode() {ch[0]=ch[1]=0;} 10 inline void newnode(tnode* &cur,int x) { 11 cur=new tnode,cur->ch[0]=cur->ch[1]=0,cur->v=x,cur->s=cur->c=1,cur->k=rand(); 12 } 13 inline void update(tnode* cur) { 14 cur->s=cur->c; 15 if (cur->ch[0]!=0) cur->s+=cur->ch[0]->s; 16 if (cur->ch[1]!=0) cur->s+=cur->ch[1]->s; 17 } 18 inline void rotate(tnode* &cur,int dir) { 19 tnode *tmp=cur->ch[dir^1]->ch[dir]; 20 if (cur->ch[dir^1]->ch[dir]==0) cur->ch[dir^1]->ch[dir]=new tnode; 21 cur->ch[dir^1]->ch[dir]=cur; 22 cur=cur->ch[dir^1]; 23 cur->ch[dir]->ch[dir^1]=tmp; 24 update(cur->ch[dir]); 25 update(cur); 26 } 27 inline void insert(tnode* &cur,int x) { 28 if (cur==NULL) {newnode(cur,x); return;} 29 if (cur->v==x) {cur->c++; cur->s++; return;} 30 bool p=cur->v<x; 31 insert(cur->ch[p],x); 32 if (cur->k>cur->ch[p]->k) rotate(cur,p^1); 33 else update(cur); 34 } 35 inline void remove(tnode* &cur,int x) { 36 if (!cur) return; 37 if (cur->v==x) { 38 if (cur->c>1) {cur->c--; cur->s--; return;} 39 if (!cur->ch[0]&&!cur->ch[1]) {cur=0; return;} 40 if (!cur->ch[0]||!cur->ch[1]) { 41 cur=cur->ch[0]?cur->ch[0]:cur->ch[1]; return; 42 } 43 bool p=cur->ch[0]->k<cur->ch[1]->k; 44 rotate(cur,p); 45 remove(cur->ch[p],x); 46 update(cur); 47 return; 48 } 49 bool p=cur->v<x; 50 remove(cur->ch[p],x); 51 update(cur); 52 } 53 inline int x_rank(tnode* cur,int x) { 54 if (!cur) return 0; 55 int s=0; 56 if (cur->ch[0]!=0) s=cur->ch[0]->s; 57 if (cur->v==x) return s+1; 58 if (cur->v>x) return x_rank(cur->ch[0],x); 59 else return s+cur->c+x_rank(cur->ch[1],x); 60 } 61 inline int rank_x(tnode* cur,int x) { 62 if (!cur) return 0; 63 int s=0; 64 if (cur->ch[0]!=0) s=cur->ch[0]->s; 65 if (x>=s+1&&x<=s+cur->c) return cur->v; 66 if (x<s+1) return rank_x(cur->ch[0],x); 67 else return rank_x(cur->ch[1],x-s-cur->c); 68 } 69 inline void x_pre(tnode* cur,int x) { 70 if (!cur) return; 71 if (cur->v>=x) x_pre(cur->ch[0],x); 72 else ans=cur->v,x_pre(cur->ch[1],x); 73 } 74 inline void x_suc(tnode* cur,int x) { 75 if (!cur) return; 76 if (cur->v<=x) x_suc(cur->ch[1],x); 77 else ans=cur->v,x_suc(cur->ch[0],x); 78 } 79 }t,*root; 80 inline int read() { 81 int x=0,f=1; char ch=getchar(); 82 while (ch<'0'||ch>'9') f=(ch=='-')?-1:1,ch=getchar(); 83 while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); 84 return x*f; 85 } 86 int main() { 87 srand(520); 88 for (int Q=read(),o,x; Q; --Q) { 89 o=read(),x=read(); 90 switch (o) { 91 case 1: t.insert(root,x); break; 92 case 2: t.remove(root,x); break; 93 case 3: printf("%d\n",t.x_rank(root,x)); break; 94 case 4: printf("%d\n",t.rank_x(root,x)); break; 95 case 5: t.x_pre(root,x); printf("%d\n",ans); break; 96 case 6: t.x_suc(root,x); printf("%d\n",ans); break; 97 } 98 } 99 return 0; 100 }
upd 2017/11/18:
学了一下splay,写了一下,神tm好难写啊。。。
题解过段时间补吧。
code:
1 #pragma GCC optimize(2) 2 #include <cstdio> 3 4 namespace OJ{ 5 void Online_Judge() { 6 #ifndef ONLINE_JUDGE 7 freopen("in.txt","r",stdin); 8 freopen("out.txt","w",stdout); 9 #endif 10 } 11 } using namespace OJ; 12 13 namespace fastIO { 14 #define gec(c) getchar(c) 15 #define puc(c) putchar(c) 16 char ch; 17 inline int read() { 18 int x=0,f=1; ch=gec(); 19 while (ch<'0'||ch>'9') { 20 if (ch=='-') f=-f; 21 ch=gec(); 22 } 23 while (ch>='0'&&ch<='9') { 24 x=(x<<3)+(x<<1)+ch-'0'; 25 ch=gec(); 26 } 27 return x*f; 28 } 29 int cnt,w[20]; 30 template <class T> inline void write(T x) { 31 if (x==0) { 32 puc('0'); return; 33 } 34 if (x<0) { 35 x=-x,puc('-'); 36 } 37 for (cnt=0; x; x/=10) w[++cnt]=x%10; 38 for (; cnt; --cnt) puc(w[cnt]+48); 39 } 40 inline void newline() { 41 puc('\n'); 42 } 43 } using namespace fastIO; 44 45 #define Splay node 46 class Splay { 47 private: 48 int s,t,v; 49 node* c[3]; 50 public: 51 node () { 52 s=t=1; 53 c[0]=c[1]=c[2]=0; 54 } 55 node* newnode (int v) ; 56 bool dir (node* x) ; 57 void upd (node* x) ; 58 void rot (node* x) ; 59 void splay (node* x,node* a) ; 60 void find (int v) ; 61 void insert (node* &x,int v) ; 62 void erase (int v) ; 63 int rank (int v) ; 64 int kth (node* x,int v) ; 65 int pre (int v) ; 66 int suc (int v) ; 67 } t,*r,*ori,*g; 68 node* Splay::newnode (int v) { 69 node* ret=new node(); 70 ret->v=v; 71 return ret; 72 } 73 bool Splay::dir (node* x) { 74 if (!x->c[2]->c[1]) return 0; 75 return x->c[2]->c[1]==x; 76 } 77 void Splay::upd (node* x) { 78 x->s=x->t; 79 if (x->c[0]) x->s+=x->c[0]->s; 80 if (x->c[1]) x->s+=x->c[1]->s; 81 } 82 void Splay::rot (node* x) { 83 bool p=dir(x); node* y=x->c[2]; 84 if (y->c[2]) y->c[2]->c[dir(y)]=x; 85 x->c[2]=y->c[2]; 86 y->c[p]=x->c[p^1]; 87 if (x->c[p^1]) x->c[p^1]->c[2]=y; 88 x->c[p^1]=y; 89 y->c[2]=x; 90 upd(y),upd(x); 91 } 92 void Splay::splay (node* x,node* o) { 93 if (x->c[2]==o) return; 94 for ( ; x->c[2]!=o; ) { 95 if (x->c[2]->c[2]==o) { 96 rot(x); 97 if (!o) r=x; 98 return; 99 } 100 if (dir(x)^dir(x->c[2])) rot(x),rot(x); 101 else rot(x->c[2]),rot(x); 102 } 103 if (!o) r=x; 104 } 105 void Splay::find (int v) { 106 for (g=r; g->v!=v; g=g->c[v>g->v]) ; 107 splay(g,0); 108 } 109 void Splay::insert (node* &x,int v) { 110 if (!x) { 111 x=g=newnode(v); 112 return; 113 } 114 if (v==x->v) { 115 ++x->s,++x->t,g=x; 116 return; 117 } 118 insert(x->c[v>x->v],v); 119 x->c[v>x->v]->c[2]=x; 120 upd(x); 121 } 122 void Splay::erase (int v) { 123 find(v); 124 if (r->t>1) { 125 --r->s,--r->t; 126 return; 127 } 128 if (!r->c[0]||!r->c[1]) { 129 if (r->c[0]) r=r->c[0],r->c[2]=0; else 130 if (r->c[1]) r=r->c[1],r->c[2]=0; 131 else r=0; 132 return; 133 } 134 for (g=r->c[0]; g->c[1]; g=g->c[1]) ; 135 splay(g,r); 136 g->c[2]=0,g->c[1]=r->c[1]; 137 if (g->c[1]) g->c[1]->c[2]=g; 138 r=g,upd(r); 139 } 140 int Splay::pre (int v) { 141 insert(r,v); 142 splay(g,0); 143 for (g=r->c[0]; g->c[1]; g=g->c[1]) ; 144 int ret=g->v; 145 erase(v); 146 return ret; 147 } 148 int Splay::suc (int v) { 149 insert(r,v); 150 splay(g,0); 151 for (g=r->c[1]; g->c[0]; g=g->c[0]) ; 152 int ret=g->v; 153 erase(v); 154 return ret; 155 } 156 int Splay::rank (int v) { 157 find(v); 158 splay(g,0); 159 int s=r->c[0]?r->c[0]->s:0; 160 return s+1; 161 } 162 int Splay::kth (node* x,int v) { 163 if (!x) return 0; 164 int s=!x->c[0]?0:x->c[0]->s; 165 if (v>s&&v<=s+x->t) return x->v; else 166 if (v<=s) return kth(x->c[0],v); 167 else return kth(x->c[1],v-s-x->t); 168 } 169 170 int Q; 171 int main() { 172 Online_Judge(); 173 r=0,Q=read(); 174 for (int q=1; q<=Q; ++q) { 175 int o=read(),x=read(); 176 switch (o) { 177 case 1: 178 t.insert(r,x),t.splay(g,0); 179 break; 180 case 2: 181 t.erase(x); 182 break; 183 case 3: 184 write(t.rank(x)),newline(); 185 break; 186 case 4: 187 write(t.kth(r,x)),newline(); 188 break; 189 case 5: 190 write(t.pre(x)),newline(); 191 break; 192 case 6: 193 write(t.suc(x)),newline(); 194 break; 195 } 196 } 197 return 0; 198 }