• 839. 模拟堆(题解细化版)


    维护一个集合,初始时集合为空,支持如下几种操作:

    1. “I x”,插入一个数x;
    2. “PM”,输出当前集合中的最小值;
    3. “DM”,删除当前集合中的最小值(数据保证此时的最小值唯一);
    4. “D k”,删除第k个插入的数;
    5. “C k x”,修改第k个插入的数,将其变为x;

    现在要进行N次操作,对于所有第2个操作,输出当前集合的最小值。

    输入格式

    第一行包含整数N。

    接下来N行,每行包含一个操作指令,操作指令为”I x”,”PM”,”DM”,”D k”或”C k x”中的一种。

    输出格式

    对于每个输出指令“PM”,输出一个结果,表示当前集合中的最小值。

    每个结果占一行。

    数据范围

    1N1051≤N≤105
    109x109−109≤x≤109
    数据保证合法。

    输入样例:

    8
    I -10
    PM
    I -10
    D 1
    C 2 8
    I 6
    PM
    DM
    

    输出样例:

    -10
    6


    个人理解:代码里的heap_swap交换映射操作

    C++代码实现
    #include<iostream>
    #include<algorithm>
    #include<string.h>
    using namespace std;
    
    const int N = 1e5 + 10;
    
    int n,m;
    int size;
    int h[N];
    
    //需要从第几个插入的点里边找到我们的元素,又需要堆里边的元素找回去,找到是第几个插入的
    //也就是第k个插入的点和堆里边的元素的映射
    
    //表示第K个插入的下标是什么是哪一个点
    int ph[N];
    
    //表示堆里面的点是第几个插入的点
    int hp[N];
    
    //具有映射的交换操作
    void heap_swap(int a,int b){
        
        //下面几个操作保证交换插入元素值之后的附加插入下标属性不变
        //也就是保证插入元素后,记录跟随第几个插入的下标元素不会变
        
        //交换第几个插入的下标的值
        swap(ph[hp[a]],ph[hp[b]]);
        
        //交换第几个插入点的下标
        swap(hp[a],hp[b]);
        
        //值进行交换
        swap(h[a],h[b]);
    }
    
    void down(int u){
        int t = u;
        if(u*2 <= size && h[u*2] < h[t]) t = u*2;
        if(u*2 + 1 <= size && h[u*2 + 1] < h[t]) t = u*2+1;
        if(t!=u){
            heap_swap(u,t);
            down(t);
        }
    }
    
    void up(int u){
        while(u / 2 && h[u/2] > h[u]){
            heap_swap(u/2,u);
            u /= 2;
        }
    }
    
    int main(){
      //初始化m记录当前是第几个插入的数
      int n,m = 0;
      scanf("%d",&n);
      
      while(n --){
          char op[10];
          
          int k,x;
          
          scanf("%s",op);
          //strcmp是<string.h>库的一个比较字符串的函数,如果相同就等于0
          if(!strcmp(op,"I")){
            scanf("%d",&x);
            size++;//堆里边多一个元素
            m++;
            
            //一开始堆里边的第m个插入元素就是在size这个位置
            ph[m] = size;
            //一开始堆里边size这个位置上的数是第m个插入进来的
            hp[size] = m;
            //当然也需要在堆中的size的位置上添加元素
            h[size] = x;
            up(size);//将元素向上怼
          }
          else if(!strcmp(op,"PM")) printf("%d
    ",h[1]);
          else if(!strcmp(op,"DM")) 
          {
              heap_swap(1,size);
              size -- ;
              down(1);
          }
          else if(!strcmp(op,"D")){
              scanf("%d",&k);
              //将第k个元素是第几个插入的取出来
              k = ph[k];
              heap_swap(k,size);
              size -- ;
              down(k),up(k);
          }
          else{
              scanf("%d%d",&k,&x);
              //拿出第k个要插入的元素
              k = ph[k];
              h[k] = x;
              down(k);
              up(k);
          }
      }
      
      return 0;
    }
    

      

     
  • 相关阅读:
    ASP.NET 防盗链的实现[HttpHandler]
    html打印表格每页都有的表头和打印分页
    spring是怎样管理mybatis的及注入mybatis mapper bean的
    浅谈Log4j和Log4j2的区别
    git tag — 标签相关操作
    java cocurrent包
    线程实现异步
    使用Shell脚本查找程序对应的进程ID,并杀死进程
    shell脚本监测文件变化
    spring boot的几种配置类型
  • 原文地址:https://www.cnblogs.com/luyuan-chen/p/11747486.html
Copyright © 2020-2023  润新知