这不算什么题解,纯属为了记录一点需要记忆的东西
我认为我把关键点都已经写了下来!
参考代码:
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int n, m, h[N], siz;
// 复杂度:O(logn)
void down(int x){
int t = x;
if(x * 2 <= siz && h[x * 2] < h[t]) t =x * 2;
if(x * 2 + 1 <= siz && h[x * 2 + 1] < h[t]) t = x * 2 + 1;
if(x != t){
swap(h[x], h[t]);
down(t);
}
}
// 复杂度:O(logn)
void up(int x){
while(x / 2 && h[x / 2] > h[x]){
swap(h[x], h[x / 2]);
x /= 2;
}
}
int main(){
cin >> n >> m;
for(int i = 1; i <= n; i++) cin >> h[i];
siz = n;
// 调整堆,总复杂度为O(n) :n / 4 * 1 + n / 8 * 2 + ... (倒数第二层个数为n / 4,最多下滤一层,类似 ...)
// 裂项相消得: 1 / 2 + 1 / 2 ^ 2 + 1 / 2 ^ 3 ... < n
// n / 2 为倒数第二层,倒数第一层已经是堆不需要处理,从下往上一次下滤一遍即可!
for(int i = n / 2; i; i--) down(i);
while(m--){
cout << h[1] << " ";
h[1] = h[siz--];
down(1);
}
return 0;
}