BZOJ 3224 Tyvj 1728 普通平衡树——treap
来源:互联网 发布:画江湖之换世门生知乎 编辑:程序博客网 时间:2024/05/16 15:54
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;}
1 0
- BZOJ 3224 Tyvj 1728 普通平衡树——treap
- 【treap】【bzoj 3224】: Tyvj 1728 普通平衡树
- 【Treap】[BZOJ 3224]Tyvj 1728 普通平衡树
- bzoj 3224: Tyvj 1728 普通平衡树 treap
- bzoj 3224: Tyvj 1728 普通平衡树 Treap
- Treap模板 BZOJ 3224: Tyvj 1728 普通平衡树
- BZOJ 3224 Tyvj 1728 普通平衡树 (Treap)
- BZOJ-3224 普通平衡树 TYVJ-1728 Treap + Vector
- Treap树堆(bzoj 3224: Tyvj 1728 普通平衡树)
- 【Treap】[BZOJ 3224]Tyvj 1728 普通平衡树 & 非旋转实现
- 3224: Tyvj 1728 普通平衡树 P3369 【模板】普通平衡树(Treap/SBT)Treap
- BZOJ 3224: Tyvj 1728 普通平衡树
- BZOJ 3224 Tyvj 1728 普通平衡树
- bzoj 3224: Tyvj 1728 普通平衡树
- 【BZOJ 3224】 Tyvj 1728 普通平衡树
- bzoj 3224/Tyvj 1728 普通平衡树
- bzoj 3224,tyvj 1728普通平衡树
- bzoj 3224: Tyvj 1728 普通平衡树
- 关于CGI的一些认识
- poj1321
- A water problem
- Fragment切换与Fragment间传值
- 【经验】 Java BigInteger类以及其在算法题中的应用
- BZOJ 3224 Tyvj 1728 普通平衡树——treap
- hibernate实现多条件组合的模糊查询
- java实现——2001计算两点间的距离
- Firefox在input标签padding上下边距过大时的bug现象
- MERGE语句用来合并UPDATE和INSERT语句,一张表的大数据操作,要同时进行增删改,提高性能
- 中国剩余定理(非互质)hdu3579 Hello Kiki ====注意刚好全部整除的情况
- Leetcode twosum
- 安装SQuirrel SQL Client连接Phoenix操作HBase
- jzoj 5001. 【NOI2017模拟3.4】Trie树 状压dp