35.Acwing基础课第839题-简单-模拟堆
35.Acwing基础课第839题-简单-模拟堆
题目描述
输入一个长度为 n 的整数数列,从小到大输出前 m 小的数。
输入格式
第一行包含整数 n 和 m。
第二行包含 n 个整数,表示整数数列。
输出格式
共一行,包含 m 个整数,表示整数数列中前 m 小的数。
数据范围
\(1≤m≤n≤10^5\)
\(1≤数列中元素≤10^9\)
输入样例:
5 3
4 5 1 3 2
输出样例:
1 2 3
代码:
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
const int N = 100010;
int h[N]; // 堆数组(1-based)
int ph[N]; // ph[k]:第k个插入的数 → 堆中的下标u
int hp[N]; // hp[u]:堆下标u → 第k个插入的数
int cnt; // 堆的当前大小
int idx; // 插入序号(第1、2...个插入)
// 自定义swap:同步维护堆值+ph+hp(核心!必须先swap映射,再swap值)
void heap_swap(int a, int b)
{
swap(ph[hp[a]], ph[hp[b]]); // 交换“插入序号→堆下标”
swap(hp[a], hp[b]); // 交换“堆下标→插入序号”
swap(h[a], h[b]); // 交换堆值
}
// down操作(仅调用heap_swap)
void down(int u)
{
int t = u;
if (u*2 <= cnt && h[u*2] < h[t]) t = u*2;
if (u*2+1 <= cnt && h[u*2+1] < h[t]) t = u*2+1;
if (u != t)
{
heap_swap(u, t);
down(t);
}
}
// up操作(仅调用heap_swap)
void up(int u)
{
while (u/2 && h[u] < h[u/2]) // u/2>0 等价于 u/2
{
heap_swap(u, u/2);
u /= 2;
}
}
// 插入:I x
void heap_insert(int x)
{
idx++; // 插入序号+1
cnt++; // 堆大小+1
ph[idx] = cnt; // 第idx个插入 → 堆下标cnt
hp[cnt] = idx; // 堆下标cnt → 第idx个插入
h[cnt] = x; // 堆尾赋值
up(cnt); // 上浮
}
// 查询最小值:PM
int heap_get_min()
{
return h[1];
}
// 删除最小值:DM(核心修复!必须先swap堆顶和堆尾,再删堆尾)
void heap_delete_min()
{
if (cnt == 0) return;
heap_swap(1, cnt); // 堆顶和堆尾交换(自动维护映射)
cnt--; // 删除堆尾(原堆顶)
down(1); // 新堆顶下沉
}
// 删除第k个插入的数:D k
void heap_delete_k(int k)
{
if (k < 1 || k > idx || ph[k] == 0) return; // 非法k直接返回
int u = ph[k]; // 第k个插入 → 堆下标u
heap_swap(u, cnt); // u和堆尾交换(维护映射)
cnt--; // 删除堆尾(原u位置的数)
down(u); // 调整u位置
up(u);
ph[k] = 0; // 清空映射(避免重复访问)
}
// 修改第k个插入的数:C k x
void heap_modify_k(int k, int x)
{
if (k < 1 || k > idx || ph[k] == 0) return;
int u = ph[k]; // 第k个插入 → 堆下标u
h[u] = x; // 修改值
down(u); // 调整
up(u);
}
int main()
{
ios::sync_with_stdio(false); // 加速cin/cout(避免超时)
cin.tie(0);
int n;
cin >> n;
while (n--)
{
string op;
cin >> op;
if (op == "I")
{
int x;
cin >> x;
heap_insert(x);
}
else if (op == "PM") cout << heap_get_min() << '\n';
else if (op == "DM") heap_delete_min();
else if (op == "D")
{
int k;
cin >> k;
heap_delete_k(k);
}
else if (op == "C")
{
int k, x;
cin >> k >> x;
heap_modify_k(k, x);
}
}
return 0;
}

浙公网安备 33010602011771号