模板题目
图片来源Acwing
堆的基础知识
代码实现
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e5 + 10;
int a[N];
int n, m;
void down(int u)
{
int t = u;
if (2 * u <= n && a[2 * u] < a[u])
{
t = 2 * u;
}
if (2 * u + 1 <= n && a[2 * u + 1] < a[t])
{
t = 2 * u + 1;
}
if (t != u)
{
swap(a[t], a[u]);
down(t);
}
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i ++)
{
cin >> a[i];
}
for (int i = n / 2; i >= 1; i --)
{
down(i);
}
while (m --)
{
cout << a[1] << ' ';
swap(a[1], a[n]);
n --;
down(1);
}
return 0;
}
进阶题目
图源Acwing
解题思路
对于前三个操作来说都十分好处理,而为了实现最后两个操作,需要引入新的数组来反映第k个插入的数和其地址下标的关系:
所引入的三个数组的基本关系如下图所示
代码实现
#include<iostream>
using namespace std;
const int N = 1e5 + 10;
int h[N], hp[N], ph[N];
int index, insert_num;
void heap_swap(int a, int b)
{
swap(h[a], h[b]);
swap(hp[ph[a]], hp[ph[b]]);
swap(ph[a], ph[b]);
}
void down(int x)
{
int min = x;
if(x * 2 <= index && h[2 * x] < h[min])
{
min = 2 * x;
}
if(x * 2 + 1 <= index && h[2 * x + 1] < h[min])
{
min = 2 * x + 1;
}
if(min != x)
{
heap_swap(x, min);
down(min);
}
}
void up(int x)
{
if(x / 2 != 0 && h[x / 2] > h[x])
{
heap_swap(x / 2, x);
up(x / 2);
}
}
void insert(int x)
{
index ++ ;
insert_num ++ ;
h[index] = x;
hp[insert_num] = index;
ph[index] = insert_num;
up(index);
}
int main()
{
int n;
cin >> n;
while(n -- )
{
string act;
cin >> act;
if(act == "I")
{
int x;
scanf("%d", &x);
insert(x);
}
else if(act == "PM")
{
printf("%d\n", h[1]);
}
else if(act == "DM")
{
heap_swap(1, index);
index -- ;
down(1);
}
else if(act == "D")
{
int k;
scanf("%d", &k);
int u = hp[k];//这里先要用u记住hp[K]的值,因为后面的heap_swap会改变hp[k]的值
heap_swap(u, index);
index -- ;
down(u);
up(u);
}
else if(act == "C")
{
int k, x;
scanf("%d%d", &k, &x);
h[hp[k]] = x;
down(hp[k]);
up(hp[k]);
}
}
return 0;
}