[luogu P3369]【模板】普通平衡树(Treap/SBT)

[luogu P3369]【模板】普通平衡树(Treap/SBT)

题目描述

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

  1. 插入x数

  2. 删除x数(若有多个相同的数,因只删除一个)

  3. 查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)

  4. 查询排名为x的数

  5. 求x的前驱(前驱定义为小于x,且最大的数)

  6. 求x的后继(后继定义为大于x,且最小的数)

输入输出格式

输入格式:

 

第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号( 1 \leq opt \leq 61opt6 )

 

输出格式:

 

对于操作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 100000n100000

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 }
View Code

 

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 }
View Code

 

转载于:https://www.cnblogs.com/whc200305/p/7744918.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值