zoukankan      html  css  js  c++  java
  • (二叉)堆

    堆可以看成一个近似的完全二叉树,其任何一非叶节点满足性质:

    Key[i]<=key[2i+1]&&Key[i]<=key[2i+2](小根堆)

    或者

    Key[i]>=Key[2i+1]&&key[i]>=key[2i+2](大根堆)

    有了上面的定义,就有下面的计算:

    #define Pa(i) i>>1 //父亲
    #define Le(i) i<<1 //左儿子
    #define Ri(i) (i<<1)+1 //右儿子
    接下来是维护堆的性质:
    一个新的i到堆中。(大根堆)
    void Mh(int i){
        int l=Le(i),r=Ri(i),lag;
        if (l<=num && heap[i]<heap[l]) lag=l;
        else lag=i;
        if (r<=num && heap[lag]<heap[r]) lag=r;
        if (lag!=i) {
            swap(heap[i],heap[lag]);
            Mh(lag);
        }
    }
    实现插入操作:
    void Hik(int i,int key){
        heap[i]=key;
        while (i>1 && heap[Pa(i)].d<heap[i].d){
            swap(heap[Pa(i)],heap[i]);
            i=Pa(i);
        }
    }
    删除最大值:
    void Hem(){
        if (num<1) {
            printf("none "); return;
        }  
        heap[1]=heap[num];
        num--; Mh(1);
        return;
    }
    这些是最基本的堆操作,其他操作可以根据这些推出。
    但我们一般不手写,因为STL中有priority_queue。
    priority_queue<int>que;默认大根堆。
    priority_queue<int, vector<int>, greater<int>> que; 小根堆。(#include<functional>//需要用到greater)
    struct cmp{

    bool operator()(int x, int y){
    return x > y; //x越小优先级越高
    }
    };
    priority_queue<int, vector<int>, cmp>que;//这个声明要特别注意两点:vector<int>和cmp

    struct node{
    int x, y;
    friend bool operator<(node a, node b){//标准库默认使用 < 来确认它们的关系,换成>就不行了哦
    return a.y>b.y;//>表示越小越优先,<表示越大越优先
    } //可以这样记:最大堆与小于号有关,最小堆与大于号有关。这样记会不会好一点呢。。。
    };
    priority_queue<node> que;

    操作:

    que.push();

    que.top();

    que.pop();

    还有映射堆:

    两个堆互相标记:

    来个题吧:

    小明的账单

    时间限制: 1 Sec  内存限制: 128 MB

    题目描述

    小明在一次聚会中,不慎遗失了自己的钱包,在接下来的日子,面对小明的将是一系列的补卡手续和堆积的账单。。。 
    在小明的百般恳求下,老板最终同意延缓账单的支付时间。可老板又提出,必须从目前还没有支付的所有账单中选出面额最大和最小的两张,并把他们付清。还没有支付的账单会被保留到下一天。 
    请你帮他计算出支付的顺序。 

    输入

    第1 行:一个正整数N(N≤15,000),表示小明补办银联卡总共的天数。 
    第2 行到第N+1 行:每一行描述一天中收到的帐单。先是一个非负整数M<=100,表示当天 
    收到的账单数,后跟M个正整数(都小于1,000,000,000),表示每张帐单的面额。 
    输入数据保证每天都可以支付两张帐单。 

    输出

    输出共N 行,每行两个用空格分隔的整数,分别表示当天支付的面额最小和最大的支 
    票的面额。 

    样例输入

    4
    3 3 6 5
    2 8 2
    3 7 1 7
    0

    样例输出

    3 6
    2 8
    1 7
    5 7
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 using namespace std;
     7 #define Pa(i) i>>1
     8 #define Le(i) i<<1
     9 #define Ri(i) (i<<1)+1
    10 #define oo 1000000000
    11 int size1,size2;
    12 struct node{
    13     int d,t;
    14 } heap_max[2000000],heap_min[2000000];
    15 void Max_h(int i){
    16     int l=Le(i),r=Ri(i),lag;
    17     if (l<=size1 && heap_max[i].d<heap_max[l].d) lag=l;
    18     else lag=i;
    19     if (r<=size1 && heap_max[lag].d<heap_max[r].d) lag=r;
    20     if (lag!=i) {
    21         heap_min[heap_max[i].t].t=lag;
    22         swap(heap_max[i],heap_max[lag]);
    23         return Max_h(lag);
    24     } 
    25 }
    26 void Min_h(int i){
    27     int l=Le(i),r=Ri(i),lag;
    28     if (l<=size2 && heap_min[i].d>heap_min[l].d) lag=l;
    29     else lag=i;
    30     if (r<=size2 && heap_min[lag].d>heap_min[r].d) lag=r;
    31     if (lag!=i) {
    32         heap_max[heap_min[i].t].t=lag;
    33         swap(heap_min[i],heap_min[lag]);
    34         return Min_h(lag);
    35     } 
    36 }
    37 void Hik_max(int i,int key){
    38     heap_max[i].d=key;
    39     while (i>1 && heap_max[Pa(i)].d<heap_max[i].d){
    40         heap_min[heap_max[i].t].t=Pa(i);
    41         swap(heap_max[Pa(i)],heap_max[i]); 
    42         i=Pa(i);
    43     }
    44 }
    45 void Hik_min(int i,int key){
    46     heap_min[i].d=key;
    47     while (i>1 && heap_min[Pa(i)].d>heap_min[i].d){
    48         heap_max[heap_min[i].t].t=Pa(i);
    49         swap(heap_min[Pa(i)],heap_min[i]); 
    50         i=Pa(i);
    51     }
    52 }
    53 void Mhi(int a){
    54     size1++; heap_max[size1].d=-oo; heap_max[size1].t=size2+1;
    55     size2++; heap_min[size2].d=oo; heap_min[size2].t=size1;
    56     Hik_max(size1,a); Hik_min(size2,a);
    57 }
    58 void Hem(){
    59     printf("%d %d
    ",heap_min[1].d,heap_max[1].d);
    60     int mint=heap_max[1].t,maxt=heap_min[1].t;
    61     heap_min[mint]=heap_min[size2];
    62     size2--; Min_h(1);
    63     heap_max[maxt]=heap_max[size1];
    64     size1--; Max_h(1);
    65     heap_min[1]=heap_min[size2];
    66     size2--; Min_h(1);
    67     heap_max[1]=heap_max[size1];
    68     size1--; Max_h(1);
    69     return;
    70 }
    71 int main()
    72 {
    73     int n; scanf("%d",&n);
    74     while (n--){
    75         int nu; scanf("%d",&nu);
    76         for (int i=1;i<=nu;i++) {
    77             int a; scanf("%d",&a);
    78             Mhi(a);
    79         } 
    80         Hem();
    81     }
    82 }
    View Code
     
     
  • 相关阅读:
    简单有效 四招教你保护好WiFi网络安全
    WP8手机安装《神庙逃亡》的教程
    如何关闭iOS7中的iPhone广告跟踪系统
    如何隐藏任务栏图标
    MVC中Controller和Action讲解上篇
    node.js
    express
    node.js+socket.io安装
    自定义view文字垂直居中
    AndroidTouch事件总结
  • 原文地址:https://www.cnblogs.com/SXia/p/6930288.html
Copyright © 2011-2022 走看看