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;
}

  

 
原文地址:https://www.cnblogs.com/luyuan-chen/p/11747486.html