您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: