BZOJ 3224 Tyvj 1728 普通平衡树——treap

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
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值