基础算法(算法竞赛)--堆排序、对顶堆第k大的数(大根堆小根堆间的动态平衡)

1、B站视频链接:A15 堆 堆排序_哔哩哔哩_bilibili

题目链接:【模板】堆 - 洛谷

#include <bits/stdc++.h> 
using namespace std;
int a[1000010],cnt;
void up(int u){//上浮 
	if(u/2&&a[u/2]>a[u]){
		swap(a[u],a[u/2]),up(u/2);
	}
}
void down(int u){//下沉 
	int v=u;//用v临时存下根节点 
	if(u*2<=cnt&&a[u*2]<a[v])v=u*2;
	if(u*2+1<=cnt&&a[u*2+1]<a[v])v=u*2+1;
	if(u!=v)swap(a[u],a[v]),down(v);
}
void push(int x){//插入 
	a[++cnt]=x;
	up(cnt);
}
void pop(){//删除 
	a[1]=a[cnt--];//用堆的尾部代替堆的顶部,并将个数减一 
	down(1);//顶部下沉 
}
int main(){
	int n;scanf("%d",&n);
	while(n--){
		int op,x;scanf("%d",&op);
		if(op==1)scanf("%d",&x),push(x);
		else if(op==2)printf("%d\n",a[1]);
		else pop();
	}	
	return 0;
}

STL代码

#include <bits/stdc++.h> 
using namespace std;
priority_queue<int,vector<int>,greater<int>>q;

int main(){
	int n;
	scanf("%d",&n);
	while(n--){
		int op,x;
		scanf("%d",&op);
		if(op==1)scanf("%d",&x),q.push(x);
		else if(op==2)printf("%d\n",q.top());
		else q.pop();
	}
	return 0;
}

2、B站视频链接:A16 对顶堆 第k大的数_哔哩哔哩_bilibili

题目链接:[CSP-J2020] 直播获奖 - 洛谷

#include <bits/stdc++.h> 
using namespace std;
priority_queue<int> a;//大根堆
priority_queue<int,vector<int>,greater<int>>b;//小根堆 

int main(){
	int n,w;
	scanf("%d%d",&n,&w);
	
	for(int i=1;i<=n;i++){
		int x;
		scanf("%d",&x);
		if(b.empty()||x>=b.top())b.push(x);//插入小根堆 
		else a.push(x);//插入大根堆 
		int k=max(1,i*w/100);//第k大 
		while(b.size()>k)a.push(b.top()),b.pop();//调整
		while(b.size()<k)b.push(a.top()),a.pop();
		printf("%d ",b.top());//取值 
	}
	return 0;
} 

练习题目:RMID2 - Running Median Again - 洛谷 

#include <bits/stdc++.h> 
using namespace std;
priority_queue<int> a;//大根堆
priority_queue<int,vector<int>,greater<int>>b;//小根堆 

int main(){
  int t,x; scanf("%d",&t); //t组数据
  while(t--){
    while(scanf("%d",&x)&&x){
      if(x>0){
        if(b.empty()||x>=b.top()) b.push(x); //插入
        else a.push(x);
        
        int k=(b.size()+a.size())/2+1; //第k大数
        while(b.size()>k) a.push(b.top()), b.pop(); //调整
        while(b.size()<k) b.push(a.top()), a.pop();        
      }
      else printf("%d\n",b.top()), b.pop(); //取值,删除
    }
  }
  return 0;
}

中位数 - 洛谷

#include <bits/stdc++.h> 
using namespace std;
priority_queue<int> a;//大根堆
priority_queue<int,vector<int>,greater<int>>b;//小根堆 

int main(){
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		int x;
		scanf("%d",&x);
		if(b.empty()||x>=b.top())b.push(x);
		else a.push(x);
		
		int k=(i+1)/2;
		while(b.size()>k)a.push(b.top()),b.pop();
		while(b.size()<k)b.push(a.top()),a.pop();
		if(i%2)printf("%d\n",b.top());//奇数取值 
	}
	return 0;
}

黑匣子 - 洛谷

最小函数值 - 洛谷

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值