主要点
该算法中,主要涉及的就是swap的写法。
唯一的办法是,自己拿出纸和笔,画一下交换过程,就马上明白了。其交换的根本是什么?
答案就是:
swap(ph[hp[u]], ph[hp[v]]);
swap(hp[u], hp[v]);
swap(h[u], h[v]);
中都是以堆中插入的元素为基准进行变换,才出现的其他两个也跟着交换。
画一下,就没问题了。
代码
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 1e5 + 10;
int hp[N], ph[N];
int h[N];
int size;
// “I x”,插入一个数x;
// “PM”,输出当前集合中的最小值;
// “DM”,删除当前集合中的最小值(当最小值不唯一时,删除最早插入的最小值);
// “D k”,删除第k个插入的数;
// “C k x”,修改第k个插入的数,将其变为x;
void heap_swap(int u, int v)
{
swap(ph[hp[u]], ph[hp[v]]);
swap(hp[u], hp[v]);
swap(h[u], h[v]);
}
void down(int u)
{
int t = u;
if (2*u <= size && h[2*u] < h[t]) t = 2*u;
if (2*u+1 <= size && h[2*u+1] < h[t]) t = 2*u+1;
if (t != u)
{
heap_swap(t, u);
down(t);
}
}
void up(int u)
{
while (u/2 && h[u] < h[u/2])
{
heap_swap(u, u/2);
u >>= 1;
}
}
int main()
{
int n;
scanf("%d", &n);
char op[3];
int a, b;
int m = 0;
while (n--)
{
scanf("%s", op);
if (!strcmp(op, "I"))
{
scanf("%d", &a);
m++;
h[++size] = a, ph[m] = size, hp[size] = m;
up(size);
}
else if (!strcmp(op, "PM")) printf("%d\n", h[1]);
else if (!strcmp(op, "DM"))
{
heap_swap(1, size);
size--;
down(1);
}
else if (!strcmp(op, "D"))
{
scanf("%d", &a);
int u = ph[a];
heap_swap(u, size);
size--;
up(u), down(u);
}
else
{
scanf("%d%d", &a, &b);
int u = ph[a];
h[u] = b;
up(u), down(u);
}
}
return 0;
}
删除第k个插入的数;
这句话是什么意思呢,如果执行这条语句之前,这个元素已经被 ( 删除当前集合中的最小值 ) 这条命令删除了,该怎么办。。还是没懂这句话是什么意思