[平衡树]BallIntheBox

原创 2012年03月27日 20:11:44

题目还是牛耳杯程序设计大赛的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;
}


 

对六种平衡树的研究与探索【全面】【更新中】

对平衡树的研究与探索四川省第七中学(高新校区) 李明洋 对平衡树的研究与探索 摘要 关键字 二叉搜索树 treap splay sbt rbt 替罪羊树 AVL 正文 一引言 二各类平衡树的基本介绍...
  • lemonoil
  • lemonoil
  • 2017年02月10日 13:53
  • 2596

几种平衡树的总结

几种平衡树的总结
  • zpcandzhj
  • zpcandzhj
  • 2014年12月03日 22:43
  • 1124

AVL树平衡因子详解

AVL树就是平衡二叉树,左子树和右子树的高度之差绝对值不超过1。 而且规定,平衡二叉树的每个节点的平衡因子只能是-1 ,1 ,0; 按照公式   平衡因子 = 右子树的高度 - 左子树...
  • Travelerwz
  • Travelerwz
  • 2016年08月11日 20:59
  • 4829

从二叉查找树到平衡二叉树再到红黑树

从二叉查找树到平衡二叉树再到红黑树的分析与实现
  • guimingyue
  • guimingyue
  • 2014年04月12日 11:10
  • 1587

判断二叉平衡树的三种方法

题目 实现一个函数,检查二叉树是否平衡。在这个问题中,平衡树的定义如下,任意一个节点,其两颗子树的高度差不超过1。 分析 判断平衡二叉树是一个常见题目,一般来说,我们都是求出左右子树的高度,根据定义判...
  • fly_yr
  • fly_yr
  • 2016年08月10日 15:33
  • 867

平衡二叉树 之 红黑树

Red-Black Tree (  RBT)也是一种自平衡二叉树,其统计性能要好于 AVL树 。它是在1972年由 鲁道夫·贝尔 发明的,它现代的名字是在 Leo J. Guibas 和 Robert...
  • whucyl
  • whucyl
  • 2013年12月11日 14:36
  • 13084

java数据结构与算法之平衡二叉树(AVL树)的设计与实现

【版权申明】未经博主同意,不允许转载!(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/53892797 出自...
  • javazejian
  • javazejian
  • 2016年12月31日 23:40
  • 7931

bzoj3224 普通平衡树【treap版】

平衡树模板题【treap版】
  • sdfzyhx
  • sdfzyhx
  • 2016年05月15日 20:59
  • 423

数据结构中常见的树(BST二叉搜索树、AVL平衡二叉树、RBT红黑树、B-树、B+树、B*树)

BST树        即二叉搜索树:        1.所有非叶子结点至多拥有两个儿子(Left和Right);        2.所有结点存储一个关键字;        3...
  • Sup_Heaven
  • Sup_Heaven
  • 2014年09月16日 12:07
  • 32347

平衡二叉树旋转原理(图示)

/************************************************************************* > File Name: btre...
  • innobase
  • innobase
  • 2016年05月02日 20:21
  • 4590
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:[平衡树]BallIntheBox
举报原因:
原因补充:

(最多只允许输入30个字)