zoukankan      html  css  js  c++  java
  • 【模板】堆【堆】

    题目大意:

    一个初始小根堆为空,我们需要支持以下3种操作:

    1. 1 x 表示将x插入到堆中
    2. 2 输出该小根堆内的最小数
    3. 3 删除该小根堆内的最小数

    思路:

    很简单,堆的模板题。维护一个小根堆即可。

    堆是什么?

    一般来说,堆是一个二叉树,它能维护一个数列的最大或最小值。
    堆又分为小根堆和大根堆,小根堆是维护最小值的(即a[1]为最小值),而大根对是维护最大值的(即a[1]为最大值)。
    时间复杂度:

    • 建堆:O(n)
    • 更改元素:O(nlogn)

    比如说,下图就是一个小根堆:
    这里写图片描述
    它符合一种特性:a[x]a[x×2]a[x]a[x×2+1]
    当我们插入一个元素时,堆会怎样维护最小值(最大值)呢?

    void up(int x)
    {
        a[++k]=x;
        int y=k;
        while(y>1&&a[y]<a[y/2])
        {
            swap(a[y],a[y/2]);
            y/=2;
        }
    }

    假设我们又插入了一个元素4。
    这里写图片描述
    它就会和他的父亲节点比较,若它的父亲节点比他大,就交换两数的位置。
    这里写图片描述
    继续,和他的父亲节点比较,6>4,交换。
    这里写图片描述
    这时再与它的父亲节点比较,由于3<4,所以就不用再往上了,维护结束,依然保证a[x]a[x×2]a[x]a[x×2+1]
    那么对应该如何删除最小值(最大值),但是依旧维护呢?
    这里一般的方法是:将点1(最小值或最大值)和点k(最后一个点)交换,再将点k下移,直到无法往下。
    比如说,我们要删除点1(点权为3的点),就先将它和最后一个点交换
    这里写图片描述
    将最后一个点(点权最小的点)删除
    这里写图片描述
    将交换上来的点下移,注意要选择两个儿子节点中点权更小的点交换(如果是大根堆就要找点权更大的点)
    这里写图片描述
    继续下移,6<13<18,将18和6交换。
    这里写图片描述
    由于没有子节点了,下移结束。
    所以,运用好这两个方法,就能很好的完成堆的题目。


    代码:

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    int n,m,x,a[5000001],k;
    
    void up(int x)  //上移
    {
        a[++k]=x;
        int y=k;
        while(y>1&&a[y]<a[y/2])
        {
            swap(a[y],a[y/2]);
            y/=2;
        }
    }
    
    void down()  //下移
    {
        swap(a[1],a[k]);
        k--;
        int x=1;
        int y=2;
        while ((y<=k&&a[x]>a[y])||(y+1<=k&&a[x]>a[y+1]))
        {
            if (a[y]>a[y+1]&&y+1<=k)  y++;  //选择更小的那一个
            swap(a[x],a[y]);
            x=y;
            y=2*x;
        }
    }
    
    int main()
    {
        scanf("%d",&n);
        while (n--)
        {
            scanf("%d",&m);
            if (m==1)  //操作1
            {
                scanf("%d",&x);
                up(x);
            }
            if (m==2)  //操作2
            {
                printf("%d\n",a[1]);
            }
            if (m==3)  //操作3
            {
                down();
            }
        }
        return 0;
    }
  • 相关阅读:
    mongodb分片
    mongodb副本集搭建
    mongodb数据导入导出
    mongodb安装、配置
    redis副本集
    redis安装,第一天
    redis常用命令
    mac中安装 RabbitMQ
    Vue常用模块
    nodejs,koa2常用模块
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/9313024.html
Copyright © 2011-2022 走看看