BZOJ 3224 Tyvj 1728 普通平衡树——treap
2017-03-06 20:43
429 查看
3224: Tyvj 1728 普通平衡树
Description您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
Input
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)
Output
对于操作3,4,5,6每行输出一个数,表示对应答案
解题思路
裸的treap,但是本人蒟蒻刚学完treap激动地想贴一下代码(指针还不是很懂,呵呵呵)。我们都知道treap是tree(二叉排序树)+heap(二叉堆),就是满足堆性质的二叉排序树,因为二叉排序树不稳(比如退化成链),所以有人想到随机一个数,使其满足堆性质,这样只有极低的概率会被卡住(几乎不可能),期望效率(log(n))。因为其他人有专门写treap的blog写的很好(比如邻居zzk神犇),我这里并不是想写解法。对于这道题大家要注意一下有负数。
#include<cstdio> #include<cstdlib> using namespace std; inline int _read(){ int sum=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9') {if (ch=='-') f=-f;ch=getchar();} while (ch>='0'&&ch<='9') sum=sum*10+ch-48,ch=getchar(); return sum*f; } struct jz{ int s,x,w,l,r,ran; }a[100005]; int n,ro,ans,tot; void Updata(int k){a[k].s=a[a[k].l].s+a[a[k].r].s+a[k].w;} void rturn(int &k){ int t=a[k].l;a[k].l=a[t].r;a[t].r=k; a[t].s=a[k].s;Updata(k);k=t; } void lturn(int &k){ int t=a[k].r;a[k].r=a[t].l;a[t].l=k; a[t].s=a[k].s;Updata(k);k=t; } void Insert(int &k,int x){ if (k==0){k=++tot;a[k].x=x;a[k].s=a[k].w=1;a[k].ran=rand();return;} a[k].s++;if (a[k].x==x) a[k].w++; else if (x<a[k].x){ Insert(a[k].l,x); if (a[a[k].l].ran<a[k].ran) rturn(k); }else{ Insert(a[k].r,x); if (a[a[k].r].ran<a[k].ran) lturn(k); } } void del(int &k,int x){ if (k==0) return; if (a[k].x==x){ if (a[k].w>1){a[k].w--;a[k].s--;return;}else if (a[k].l*a[k].r==0) k=a[k].l+a[k].r;else if (a[a[k].l].ran<a[a[k].r].ran){rturn(k);del(k,x);}//这里原来写成了大根堆,深感抱歉,感谢CHNWJD大神的指正 else {lturn(k);del(k,x);} }else if (x<a[k].x) a[k].s--,del(a[k].l,x);else a[k].s--,del(a[k].r,x); } int ask1(int k,int x){ if (k==0) return 0; if (a[k].x==x) return a[a[k].l].s+1; else if (x<a[k].x) return ask1(a[k].l,x); else return a[a[k].l].s+a[k].w+ask1(a[k].r,x); } int ask2(int k,int x){ if (k==0) return 0; if (x<=a[a[k].l].s) return ask2(a[k].l,x); else if (x>a[a[k].l].s+a[k].w) return ask2(a[k].r,x-a[a[k].l].s-a[k].w); else return a[k].x; } void pre(int k,int x){ if (k==0) return; if (a[k].x<x){ans=a[k].x;pre(a[k].r,x);}else pre(a[k].l,x); } void sub(int k,int x){ if (k==0) return; if (a[k].x>x){ans=a[k].x;sub(a[k].l,x);}else sub(a[k].r,x); } int main(){ freopen("exam.in","r",stdin); freopen("exam.out","w",stdout); n=_read(); while (n--){ int y=_read(),x=_read(); switch(y){ case 1:Insert(ro,x);break; case 2:del(ro,x);break; case 3:printf("%d\n",ask1(ro,x));break; case 4:printf("%d\n",ask2(ro,x));break; case 5:ans=0,pre(ro,x),printf("%d\n",ans);break; case 6:ans=0,sub(ro,x),printf("%d\n",ans);break; } } return 0; }
我良(zhong)心(yu)发(xue)现(hui)指针版,感谢各位dalao指正
#include<cstdio> #include<cstdlib> using namespace std; const int maxn=100005; struct jz{ jz* son[2]; int x,w,rd,s; int cmp(int k){if (k<x) return 0;else if (k==x) return -1;else return 1;} void updata(){s=son[0]->s+son[1]->s+w;} }; jz a[maxn],*null=a,*ro=null; int m,tot; inline int _read(){ int num=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-f;ch=getchar();} while (ch>='0'&&ch<='9') num=num*10+ch-48,ch=getchar(); return num*f; } jz* newnode(int x){ a[++tot].w=a[tot].s=1;a[tot].x=x;a[tot].rd=rand(); a[tot].son[0]=a[tot].son[1]=null; return &a[tot]; } void turn(jz* &k,int p){ jz* t=k->son[p];k->son[p]=t->son[p^1];t->son[p^1]=k; t->updata();k->updata();k=t; } void Insert(jz* &k,int x){ if (k==null) {k=newnode(x);return;} int p=k->cmp(x); if (p==-1) k->w++;else{ Insert(k->son[p],x); if (k->son[p]->rd>k->rd) turn(k,p); } k->updata(); } void del(jz* &k,int x){ if (k==null) return; int d=k->cmp(x); if (d==-1){ if (k->w>1) k->w--;else if (k->son[0]==null) k=k->son[1];else if (k->son[1]==null) k=k->son[0];else{ int son;if (k->son[0]->rd>k->son[1]->rd) son=0;else son=1; turn(k,son);if(k==null) return;del(k->son[son^1],x); } if (k==null) return; }else del(k->son[d],x); k->updata(); } int ask1(jz* k,int x){ if (k==null) return 0; int d=k->cmp(x); if (d==0) return ask1(k->son[0],x);else if (d==-1) return k->son[0]->s+1;else return k->son[0]->s+k->w+ask1(k->son[1],x); } int ask2(jz* &k,int y){ if (k==null) return 0; if (y<=k->son[0]->s) return ask2(k->son[0],y);else if (y>k->son[0]->s+k->w) return ask2(k->son[1],y-k->son[0]->s-k->w);else return k->x; } int ask3(jz* &k,int y){ if (k==null) return 0; int d=k->cmp(y); if (d==0){int x=ask3(k->son[0],y);if (x==0) return k->x;else return x; }else return ask3(k->son[1],y); } int ask4(jz* &k,int y){ if (k==null) return 0; int d=k->cmp(y); if (d==1){int x=ask4(k->son[1],y);if (x==0) return k->x;else return x; }else return ask4(k->son[0],y); } int main(){ freopen("exam.in","r",stdin); freopen("exam.out","w",stdout); m=_read(); while (m--){ int x=_read(),y=_read(); if (x==1) Insert(ro,y); if (x==2) del(ro,y); if (x==3) printf("%d\n",ask1(ro,y)); if (x==4) printf("%d\n",ask2(ro,y)); if (x==5) printf("%d\n",ask4(ro,y)); if (x==6) printf("%d\n",ask3(ro,y)); } return 0; }
相关文章推荐
- BZOJ3224 Tyvj 1728 普通平衡树(Treap)
- bzoj 3224: Tyvj 1728 普通平衡树 treap
- BZOJ-3224 普通平衡树 TYVJ-1728 Treap + Vector
- BZOJ3224[Tyvj 1728 普通平衡树]题解--Treap
- BZOJ 3224: Tyvj 1728 普通平衡树 treap
- BZOJ 3224 Tyvj 1728 普通平衡树 (Treap)
- 【treap】【bzoj 3224】: Tyvj 1728 普通平衡树
- 【模板】【bzoj3224】Tyvj 1728 普通平衡树 Treap
- Treap模板 BZOJ 3224: Tyvj 1728 普通平衡树
- bzoj3224 Tyvj 1728 普通平衡树(splay/treap)
- [BZOJ3224]Tyvj 1728 普通平衡树 && treap
- 【Treap】[BZOJ 3224]Tyvj 1728 普通平衡树 & 非旋转实现
- 【bzoj3224】Tyvj 1728 普通平衡树 01Trie姿势+平衡树的四种姿势 :splay,旋转Treap,非旋转Treap,替罪羊树
- Treap树堆(bzoj 3224: Tyvj 1728 普通平衡树)
- bzoj3224 Tyvj 1728 普通平衡树 treap
- BZOJ 3224: Tyvj 1728 普通平衡树 treap
- BZOJ 3224 TYVJ 1728 普通平衡树 [Treap树模板]
- bzoj3224Tyvj 1728 普通平衡树 treap
- (treap)[bzoj3224][洛谷3369][cogs1829]Tyvj 1728 普通平衡树
- 【Treap】[BZOJ 3224]Tyvj 1728 普通平衡树