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
原创粉丝点击