发布时间 2023-12-29 13:00:58作者: Lost-in-love

堆(洛谷P3378)


题目大意

建立支持以下三种操作的堆:

  • 输入1 x,将x插入堆中
  • 输入2,输出堆的最小值
  • 输入3,删除堆的最大值

解题思路

手写堆或者使用STL容器实现。

手写堆
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int heap[N],top=0;
void push(int x){
	heap[++top]=x;
	for(int i=top;i>1&&heap[i]<heap[i>>1];i>>=1)swap(heap[i],heap[i>>1]);
}
void pop(){
	heap[1]=heap[top--];
	for(int i=1;(i<<1)<=top;){
		int son=i<<1;
		if(son<top&&heap[son+1]<heap[son])son++;
		if(heap[son]<heap[i]){
			swap(heap[son],heap[i]);
			i=son;
		}else break;
	}
}
int main(){
	int n;
	cin>>n;
	while(n--){
		int op,x;
		cin>>op;
		if(op==1){
			cin>>x;
			push(x);
		}else if(op==2)cout<<heap[1]<<endl;
		else pop();
	}
	return 0;
}

STL
#include<bits/stdc++.h>
using namespace std;
priority_queue<int,vector<int>,greater<int>>q;
int n;
int main(){
	cin>>n;
	int op,a;
	while(n--){
		cin>>op;
		switch(op){
			case 1:cin>>a;
			q.push(a);
			break;
			case 2:cout<<q.top()<<endl;
			break;
			case 3:q.pop();
		}
	}
	return 0;
}

合并果子(洛谷P1090)


题目大意

对序列a合并元素至只包含一个元素,合并代价为元素值之和。求最小代价。

解题思路

根据贪心思想,优先合并值小的元素,由于合并后会产生新元素需要更新值,故采用堆即优先队列存储。每次合并最小的两个元素,并将合并值入堆。最后输出总和即可。

未知的代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e4+5;
priority_queue<int,vector<int>,greater<int>>q;
int n;
int main(){
	cin>>n;
	int a,ans=0;
	while(n--){
		cin>>a;
		q.push(a);
	}
	while(q.size()>1){
		int x=q.top();
		q.pop();
		int y=q.top();
		q.pop();
		ans+=(x+y);
		q.push(x+y);
	}
	cout<<ans<<endl;
	return 0;
}

中位数(洛谷P1168)


题目大意

给定一个长度为N的非负整数序列A,对于前奇数项求中位数。

解题思路

使用两个堆,一个大根堆,堆顶存最大值,一个小根堆,堆顶存最小值,这样对于中位数而言小于等于中位数的存放在大根堆,大于的存在小根堆。最后保证大根堆元素数等于小根堆元素数即可。mid即更新为中位数。

未知的代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	priority_queue<int>q1;	//大根堆
	priority_queue<int,vector<int>,greater<int>>q2;	//小根堆
	int n,mid,x;
	cin>>n>>mid;
	cout<<mid<<endl; //前1项
	for(int i=2;i<=n;i++){
		cin>>x;
		if(x>mid)q2.push(x);
		else q1.push(x);
		if(i%2){
			while(q1.size()!=q2.size()){
				if(q1.size()>q2.size()){
					q2.push(mid);
					mid=q1.top();
					q1.pop();
				}else{
					q1.push(mid);
					mid=q2.top();
					q2.pop();
				}
			}
			cout<<mid<<endl;
		}
	}
	return 0;
}

最小函数值(洛谷P2085)


题目大意

给定n个函数\(F_i(x)=A_ix^2+B_ix+C_i\)\(A_i,B_i,C_i\)均给出,均为正整数,求所有函数所有函数值最小的m个,如果最小值有重复需重复输出。

解题思路

由于函数各项系数均为正整数已知函数单调递增,所以对每个函数从1到m取值,计算函数值,使用优先队列存最小值。

未知的代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
int main(){
	priority_queue<int>q;
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		int a,b,c;
		cin>>a>>b>>c;
		for(int j=1;j<=m;j++){
			if(i==1)q.push(a*j*j+b*j+c);
			else{
				int  k=a*j*j+b*j+c;
				if(k<q.top()){
					q.push(k);
					q.pop();
				}else break;
			}
		}
	}
	vector<int>ret;
	while(m--){
		ret.push_back(q.top());
		q.pop();
	}
	for(int i=ret.size()-1;i>=0;i--)cout<<ret[i]<<" ";
	return 0;
}

蚯蚓(洛谷P2827)


题目大意


解题思路

未知的代码


Cow Coupons G(洛谷P3045)


题目大意


解题思路

未知的代码