AcWing 786. 写个堆解法
原题链接
简单
作者:
钝刀幽灵
,
2024-09-27 12:47:50
,
所有人可见
,
阅读 3
算法1
#include<bits/stdc++.h>
using namespace std;
const int N = 5e6 + 1;
long long int a[N];
long long int Heap[N];
int n,k;
int len = 0;
void insert(int x){ //建堆
if(len == 1){
Heap[len] = x;
return ;
}
Heap[len] = x; //插入新元素时,放到堆尾
for(int i = len;i > 1;i/=2){ //比较父亲结点,大于父结点则交换位置,直至无法上升
if(Heap[i] > Heap[i/2]){
swap(Heap[i],Heap[i/2]);
}else{
return ;
}
}
}
void adjust(int x)
{
if(x < Heap[1]){ // 比较堆顶元素,若插入元素小于堆顶,则取代堆顶元素
if(len == 1){
Heap[1] = x;
return ;
}
int kk = 1; // kk 为当前处理堆的根节点
Heap[0] = x; //保存插入元素
for(int i = 2*kk;i <= len;i *= 2){
if(i + 1<= len and Heap[i] < Heap[i + 1]){ //选择左右孩子中较大的元素
i ++;
}
if(Heap[0] >= Heap[i]){ //插入元素大于等于较小的元素则无需继续向下下坠
break;
}
else{
Heap[kk] = Heap[i];
kk = i; //更新根结点i,处理以i为根结点的子树
}
}
Heap[kk] = Heap[0];
}
}
int main()
{
scanf("%d %d",&n,&k);
for(int i = 1;i <= n;i ++){
scanf("%d",&a[i]);
}
for(int i = 1;i <= n;i ++){
if(len < k){
len ++;
insert(a[i]); //建大小为k的小顶堆
}else{
adjust(a[i]); //比较插入元素和堆顶元素
}
}
printf("%d",Heap[1]); //大小为k的大顶堆的堆顶元素就是第k大的元素
return 0;
}
大小为k的大顶堆的堆顶元素就是第k小的元素