双端堆/最小-最大堆/Double-Ended Heap ?

本文介绍了如何使用双端堆(最小-最大堆)解决Uva 11136 - Hoax or what问题,该问题需要查找并删除最小值和最大值。双端堆允许常数时间查询和O(log(n))时间复杂度的删除操作。论文链接提供了一个关于双端堆插入操作的详细探讨,但删除操作的实现可能存在问题,导致在Uva平台上提交失败,作者寻求解释和帮助。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      Uva 11136 - Hoax or what 这道题可以用优先队列做,这里讨论一下用最小-最大堆做。

      题目的要求:需要找到最小值和最大值,并且还有删除最小值和最大值。

      这样就需要一种包括下面几种操作的数据结构:

  • insert 插入一个元
  • get_min() 得到最小元素,并将其从集合中删除
  • get_max()的到最大元素,并将其从集合中删除

     如果只是需要找到最小值或者最大值,那么可以用heap,也可以用优先队列。但是这里需要找到最小值和最大值,还是可以用heap,也就是双端堆/最小-最大堆/Double-Ended Heap 。

     查询效率为常数,删除效率为O(log(n))

     下面附上一篇论文: http://pan.baidu.com/share/link?shareid=1020027175&uk=70243437

       所谓的最小-最大堆,就是在一个二叉树中同时维护两个堆(最小堆和最大堆)的性质。最开始的最小-最大堆是最小堆和最大堆一次按照二叉树树深交替出现,但是这里的最小-最大堆是左子树为最小堆,右子树为最大堆,且左兄弟不能大于右兄弟。

     论文只讲了如何插入元素,因为删除最大元素和最小元素和普通的heap操作差不多。在删除操作中充分利用最小-最大堆的限制就可以很轻松的写出代码。下面的代码不知道正确否,因为在Uva上提交时显示提交错误,换了几个号都是,求解释啊。

   

    /*最小-最大堆的实现
       不断的维护这样一个二叉树:左子树为最小堆,右子树为最大堆
       有三个操作:
       插入 插入的同时维护最小-最大堆的性质
       返回最大值 返回的同时删除最大值,并维护最小-最大堆的性质
       返回最小值 返回的同时删除最小值,并维护最小-最大堆的性质
    */
    #include <stdio.h>
    #include <string.h>
    #define maxn 100100
    struct heap
    {
        int len;
        int a[maxn];
        void init()
        {
            len = 0;
            memset(a,0,sizeof(0));
        }
        void heap_insert(int x)
        {
            int p = ++len;
            int gf;
            int l,r;
            while(1)
            {
                if(!(p&1) && a[p-1] > x)
                {
                    a[p] = a[p-1];
                    p--;
                }
                gf = ((p+1) >> 2)-1;
                if(gf < 0) break;
                if(gf == 0) l = 1,r = 2;
                else l = (gf<<1) +1,r = l + 1;
                if(x < a[l]) a[p] =a[l],p = l;
                else if(x > a[r]) a[p] = a[r],p = r;
                else break;
            }
            a[p] = x;
        }
        int get_min()
        {
            int p = 1;
            int Min = a[p];
            int temp;
            a[p] = a[len--];
            while(1)
            {
                if((p&1) && p+1 <= len && a[p] > a[p+1])
                {
                    temp = a[p+1];
                    a[p+1] = a[p];
                    a[p] = temp;
                }
                int lchild = (p<<1) + 1;
                if(lchild > len) break;
                if(a[p] > a[lchild])
                {
                    temp = a[p];
                    a[p] = a[lchild];
                    a[lchild] = temp;
                }
                else break;
            }
            return Min;
        }
        int get_max()
        {
            int p = 2;
            int Max = a[p];
            int temp;
            a[p] = a[len--];
            while(1)
            {
                if(!(p&1) && p-1 >= 1 && a[p] < a[p-1])
                {
                    temp = a[p];
                    a[p] = a[p-1];
                    a[p-1] = a[p];
                }
                int rchild = (p<<1)+2;
                if(rchild > len) break;
                if(a[p] < a[rchild])
                {
                    temp = a[rchild];
                    a[rchild] = a[p];
                    a[p] = a[rchild];
                }
                else break;
            }
            return Max;
        }
    } h;
    int ans;
    int n,m;
    int main()
    {
        while(scanf("%d",&n) && n)
        {
            h.init();
            ans = 0;
            while(n--)
            {
                scanf("%d",&m);
                int x;
                while(m--)
                {
                    scanf("%d",&x);
                    h.heap_insert(x);
                }
                int Max = h.get_max();
                int Min = h.get_min();
                ans += Max - Min;
            }
            printf("%d\n",ans);
        }
        return 0;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值