作者:
卷死你们QAQ
,
2023-03-15 20:33:42
,
所有人可见
,
阅读 12
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010;
int a[N];//保存数组
int n, m;//n个点,求前m小
int r ;//堆得右边界
void down(int u)//调整函数
{
//t记录最小点的编号
int t = u;
//有左儿子,并且左儿子比t节点的值小,更新t
if(2 * u <= r && a[2 * u] < a[t]) t = 2 * u;
//有右儿子,并且右儿子比t节点的值小,更新t
if(2 * u + 1 <= r && a[2 * u + 1] < a[t]) t = 2 * u + 1;
//如果待调整点不是最小的
if(u != t)
{
//和最小的交换
swap(a[u], a[t]);
//递归处理
down(t);
}
}
int main()
{
cin >> n >> m;
r = n;//开始时,右边界是数组边界
//读入数据
for (int i = 1; i <= n; i ++ )
{
int x;
cin >> a[i];
}
//从第一个非叶节点开始,从右到左,从下到上处理每个节点
for(int i = n /2 ; i >= 1; i--)
{
down(i);
}
//输出m个最小值
while (m -- )
{
//堆顶保存的最小值,输出堆顶
cout << a[1] << " ";
//将堆顶和右边界交换
swap(a[1], a[r]);
//右边界左移
r--;
//从新处理堆顶
down(1);
}
}