Acwing 838. 堆排序
题目描述
输入一个长度为 n
的整数数列,从小到大输出前 m 小的数。
输入格式
第一行包含整数 n 和 m。
第二行包含 n个整数,表示整数数列。
输出格式
共一行,包含 m 个整数,表示整数数列中前 m 小的数。
数据范围
1≤m≤n≤105,
1≤数列中元素≤109
思路
建立一个堆,即一颗树,每个父节点一定大于两个根节点。
如何维护?只需一个操作,即下降,如果一个数字比一个子节点小就和子节点交换,如何递归这个操作。
代码
#include<iostream>
using namespace std;
const int N = 1000010;
int h[N],cnt,n,m;
void down(const int x)
{
int t = x;
if(h[t] > h[2*x] && 2*x <= cnt ) t = 2*x;
if(h[t] > h[2*x+1] && 2*x+1 <= cnt) t =2*x+1;
if(t != x)
{
swap(h[t],h[x]);
down(t) ;
}
return ;
}
int main()
{
cin>>n>>m;
cnt = n;
for(int i = 1 ;i <= n ; ++ i) scanf("%d",&h[i]);
for(int i = n/2 ; i ; -- i) down(i);
while (m -- )
{
printf("%d ", h[1]);
h[1] = h[cnt -- ];
down(1);
}
return 0;
}