维护一个集合,初始时集合为空,支持如下几种操作:
I x
,插入一个数 xx;PM
,输出当前集合中的最小值;DM
,删除当前集合中的最小值(数据保证此时的最小值唯一);D k
,删除第 kk 个插入的数;C k x
,修改第 kk 个插入的数,将其变为 xx;
现在要进行 NN 次操作,对于所有第 22 个操作,输出当前集合的最小值。
输入格式
第一行包含整数 NN。
接下来 NN 行,每行包含一个操作指令,操作指令为 I x
,PM
,DM
,D k
或 C k x
中的一种。
输出格式
对于每个输出指令 PM
,输出一个结果,表示当前集合中的最小值。
每个结果占一行。
数据范围
1≤N≤1051≤N≤105
−109≤x≤109−109≤x≤109
数据保证合法。
输入样例:
8
I -10
PM
I -10
D 1
C 2 8
I 6
PM
DM
输出样例:
-10
6
这道题首先要理解ph【】和hp【】数组的含义:
ph[]存的是堆里的下标(第k个插入的点是堆里的那个点)
hp[]存的是第k个插入的点(堆里的莫一个点是第几个插入的点)
上面两行是y总讲的原话,然后我的理解是,ph【】里面的坐标是第k个数,对应的值是堆里面的坐标;hp【】里面的坐标是堆里面的数,对应的值是插入的第k个数。
所以ph【】的值我对应的是sz(因为有size函数,所以我设置的变量是sz),hp【】的值我对应的是idx。
然后这个比堆排序多了个函数,eswap(end swap)这是我自己设的名字hh,调用的两个值a,b,是堆里面的坐标,不是插入的坐标,也就是sz而不是idx。
然后在交换q【】的值的之前,要把ph【】和hp【】的映射给交换,没有顺序可言,就是说不管是ph【hp【】】 , hp【】 还是hp【ph【】】,ph【】 ,都是一样的意义。
不要忘记把down和up的swap给改一下,然后我自己敲代码的时候,一直答案错误,分享一下我的错误是什么:
我在down的时候,以为t既然=u了,所以if里面u,t都是一样的,所以u和t我都写的t,然后发现答案是错的,为什么呢,因为有两个if,在第一个if成立的时候,t的值已经变了,在进行第二个if的时候,t * 2 就等于 u*4了。
然后简单讲解一下
I 插入的坐标和堆坐标都加一,q【sz】 = x,然后就是上面讲的ph【idx】= sz ,(里面idx插入坐标 对应 堆的坐标)然后up(sz)让这个新插入的数和它的父节点或祖宗节点比较交换。
PM 输出根节点
DM 交换根节点和最后一个点,整体sz-1,然后把根节点往下down
D 找出k的对应堆坐标,因为这里的k是第k个插入的数,可以自己理解一下,然后从k点down,up,往上往下都比较一遍
最后一个跟D同理
代码:
对了,下面strcmp里面是两个字符串比较,相等的话返回0,包含在cstring = string.h 的库中
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std ;
const int N = 1e5 + 50;
int idx = 0 ,sz = 0 , q[N] , ph[N] , hp[N];
void eswap(int a ,int b)
{
swap(ph[hp[a]], ph[hp[b]]);//这里要交换映射关系,知道一个元素在堆中的位置从而通过ph[hp[a]映射出在数组中的位置i, j
swap(hp[a], hp[b]);//交换在堆中的位置
swap(q[a], q[b]);
}
void down(int u)
{
int t = u ;
if(u * 2 <= sz&& q[t] > q[u * 2]) t = u * 2 ;
if(u * 2 + 1 <= sz && q[t] > q[u * 2 + 1 ]) t = u * 2 + 1 ;
if(u!= t)
{
eswap(u, t) ;
down(t);
}
}
void up(int u)
{
while(u / 2 && q[u/2] > q[u] )
{
eswap(u , u / 2);
u = u / 2 ;
}
}
int main()
{
int n ;
cin >> n ;
while(n--)
{
char op[5] ;
int k , x ;
scanf("%s" , op);
if(!strcmp(op,"I"))
{
cin >> x ;
idx ++ ,sz ++ ;
q[sz] = x ;
ph[idx] = sz , hp[sz] = idx;
up(sz);
}
else if (!strcmp(op,"PM"))cout << q[1] << endl;
else if (!strcmp(op,"DM"))
{
eswap(1 , sz) ;
sz -- ;
down(1);
}
else if (!strcmp(op,"D"))
{
cin >> k ;
k = ph[k] ;
eswap(k , sz) ;
sz -- ;
down(k) , up(k) ;
}
else
{
cin >> k >> x ;
k = ph[k] ;
q[k] = x ;
down(k) , up(k);
}
}
return 0 ;
}