AcWing 839. 模拟堆

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

“I x”,插入一个数x;
“PM”,输出当前集合中的最小值;
“DM”,删除当前集合中的最小值(数据保证此时的最小值唯一);
“D k”,删除第k个插入的数;
“C k x”,修改第k个插入的数,将其变为x;
现在要进行N次操作,对于所有第2个操作,输出当前集合的最小值。

输入格式
第一行包含整数N。

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

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

每个结果占一行。

数据范围
1≤N≤105
−109≤x≤109
数据保证合法。

输入样例:
8
I -10
PM
I -10
D 1
C 2 8
I 6
PM
DM
输出样例:
-10
6
难度: 简单
时/空限制: 1s / 64MB

#include <iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
const int N=100010;
int h[N],siz;
int ph[N];//第k个插入数的下标
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 x)
{
  int t=x;
  if(x*2<=siz&&h[x*2]<h[t])t=x*2;
  if(x*2+1<=siz&&h[x*2+1]<h[t])t=2*x+1;
  if(x!=t)
  {
    heap_swap(x,t);
    down(t);
  }
}
void up(int x)
{
  while(x/2&&h[x/2]>h[x])
  {
    heap_swap(x/2,x);
    x/=2;  
  }
}
int main()
{
    int n;
    int m=0;
    cin>>n;
    while(n--)
    {
      char op[10];
      cin>>op;
      int k,x;
      if(!strcmp(op,"I"))
      {
        cin>>x;
        siz++;
        m++;
        ph[m]=siz; 
        hp[siz]=m;
        h[siz]=x;
        up(siz);
      }
      else if(!strcmp(op,"PM"))printf("%d\n",h[1]);
      else if(!strcmp(op,"DM"))
      {
        heap_swap(1,siz);
        siz--;
        down(1);
      }
      else if(*op=='D')
      {
        cin>>k;
        k=ph[k];
        heap_swap(k,siz);
        siz--;
        down(k);
        up(k);
      }
      else
      {
        cin>>k>>x;
        k=ph[k];
        h[k]=x;
        down(k),up(k); 
      }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值