[平衡树]BallIntheBox

来源:互联网 发布:天人网络电视在线 编辑:程序博客网 时间:2024/05/21 04:41

题目还是牛耳杯程序设计大赛的D题,之前已经描述过,就不在赘述了。

之前用AVL实现的,这里附上一个用SBT实现的版本,对比发现SBT实现更为简单,而且时空消耗略少。

 

搓长丑的SBT代码:

#include<iostream>#include<cstdio>#include<algorithm>#include<memory.h>#include<ctime>using namespace std;const int MAXN = 100010;struct KEY{    int wgt;    int num;    KEY(int w=0,int n=0):wgt(w),num(n){}    bool operator == (const KEY &k) const    {         return wgt==k.wgt&&num==k.num;    }    bool operator < (const KEY &k) const    {         if(wgt!=k.wgt)return wgt<k.wgt;         return num<k.num;    }};struct SBT{    int l[MAXN],r[MAXN],size[MAXN],pool[MAXN],ROOT,TOP,NODE;    KEY Key[MAXN];    void init()    {         TOP = NODE = ROOT = 0;    }    int newnode(int w,int n)   {        int node;        if(TOP)node = pool[TOP--];        else node = ++NODE;        Key[node].wgt = w;        Key[node].num = n;        size[node] = 1;        l[node] = r[node] = 0;        return node;   }   void delnode(int x)   {        pool[++TOP] = x;        Key[x].wgt = Key[x].num = size[x] = l[x] = r[x] = 0;   }   void left_rotate(int &p)   {        int x = r[p];        r[p] = l[x];        l[x] = p;        size[p] = size[l[p]]+size[r[p]]+1;        size[x] = size[l[x]]+size[r[x]]+1;        p = x;   }   void right_rotate(int &p)   {        int x = l[p];        l[p] = r[x];        r[x] = p;        size[p] = size[l[p]]+size[r[p]]+1;        size[x] = size[l[x]]+size[r[x]]+1;        p = x;   }   void Maintain(int &p)   {        if(size[l[l[p]]]>size[r[p]])        {            right_rotate(p);            Maintain(r[p]);            Maintain(p);        }        if(size[r[l[p]]]>size[r[p]])        {            left_rotate(l[p]);            right_rotate(p);            Maintain(l[p]);            Maintain(r[p]);            Maintain(p);        }        if(size[r[r[p]]]>size[l[p]])        {            left_rotate(p);            Maintain(l[p]);            Maintain(p);        }        if(size[l[r[p]]]>size[l[p]])        {            right_rotate(r[p]);            left_rotate(p);            Maintain(r[p]);            Maintain(l[p]);            Maintain(p);        }   }   void Maintain_faster(int &p,bool flag)   {        if(flag==0)        {            if(size[l[l[p]]]>size[r[p]])right_rotate(p);            else if(size[r[l[p]]]>size[r[p]])            {                 left_rotate(l[p]);                 right_rotate(p);            }            else return ;        }        else        {            if(size[r[r[p]]]>size[l[p]])left_rotate(p);            else if(size[l[r[p]]]>size[l[p]])            {                 right_rotate(r[p]);                 left_rotate(p);            }            else return;        }        Maintain_faster(l[p],0);        Maintain_faster(r[p],1);        Maintain_faster(p,1);        Maintain_faster(p,0);   }   void insert(int &p,KEY k)   {        if(!p)        {              p = newnode(k.wgt,k.num);              return;        }        if(k<Key[p])insert(l[p],k);        else insert(r[p],k);        size[p]=size[l[p]]+size[r[p]]+1;        Maintain_faster(p,!(k<Key[p]));   }   int findmin(int p)   {       if(l[p])return findmin(l[p]);       else return p;   }   void remove(int &p,KEY k)   {        if(p)        {            if(k==Key[p])            {                if(!l[p])                {                    int x = p;                    p = r[p];                    delnode(x);                }                else if(!r[p])                {                    int x = p;                    p = l[p];                    delnode(x);                }                else                {                    int x = findmin(r[p]);                    Key[p] = Key[x];                    remove(r[p],Key[x]);                }            }            else if(k<Key[p])remove(l[p],k);            else remove(r[p],k);            if(p){               size[p] = size[l[p]]+size[r[p]]+1;            }            //Maintain(p);        }   }   int Select(int p,int k)   {       int rank = size[l[p]]+1;       if(rank==k)return p;       else if(rank<k)return Select(r[p],k-rank);       return Select(l[p],k);   }   void print(int p)   {       if(!p)return;       print(l[p]);       printf("%d\n",size[p]);       print(r[p]);   }}sbt;int A[MAXN];int main(){    clock_t start,final;    start = clock();    int n,m;    freopen("D.in","r",stdin);    freopen("Dans.out","w",stdout);    while(scanf("%d%d",&n,&m)!=EOF)    {        sbt.init();        for(int i=1;i<=n;i++)scanf("%d",&A[i]);        for(int i=1;i<=n;i++)sbt.insert(sbt.ROOT,KEY(A[i],i));        for(int i=0;i<m;i++)        {            int x,y;char op[5];            scanf("%s",op);            //sbt.print(sbt.ROOT);            if(op[0]=='A')            {                scanf("%d%d",&x,&y);                sbt.remove(sbt.ROOT,KEY(A[x],x));                A[x]+=y;                sbt.insert(sbt.ROOT,KEY(A[x],x));            }            else if(op[0]=='B')            {                scanf("%d%d",&x,&y);                sbt.remove(sbt.ROOT,KEY(A[x],x));                A[x]-=y;                sbt.insert(sbt.ROOT,KEY(A[x],x));            }            else if(op[0]=='C')            {                scanf("%d%d",&x,&y);                sbt.remove(sbt.ROOT,KEY(A[x],x));sbt.remove(sbt.ROOT,KEY(A[y],y));                A[y]+=A[x];                sbt.insert(sbt.ROOT,KEY(A[y],y));            }            else            {                scanf("%d",&x);                printf("%d\n",sbt.Key[sbt.Select(sbt.ROOT,x)].wgt);            }        }    }    final = clock();    printf("Time is %lf\n",(double)(final-start)/CLOCKS_PER_SEC);    return 0;}