A - 1-1 寻找大富翁 HDU - 3785

这篇文章介绍了如何使用优先队列优化算法来解决浙江桐乡乌镇寻找前m个大富翁的问题,通过对比两种方法并展示了高效的时间复杂度。

A - 1-1 寻找大富翁 HDU - 3785

Statement

浙江桐乡乌镇共有n个人,请找出该镇上的前m个大富翁.

Input

输入包含多组测试用例.
每个用例首先包含2个整数n(0<n<=100000)和m(0<m<=10),其中: n为镇上的人数,m为需要找出的大富翁数, 接下来一行输入镇上n个人的财富值.

n和m同时为0时表示输入结束.

Output

请输出乌镇前m个大富翁的财产数,财产多的排前面,如果大富翁不足m个,则全部输出,每组输出占一行.

Sample

Input

3 1
2 5 -1
5 3
1 2 3 4 5
0 0

Output

5
5 4 3

Solution

一开始直接sort TEL了三发 sort 的是时间复杂度是 N*log( N )

后面用了priority_queue

top( ) 读一个

pop( ) 弹一个出来

priority_queue 的时间复杂度是 log( N )

push(x)
将元素x压入priority_queue,时间复杂度为log(N)

top()
取队首元素,即堆顶元素,时间复杂度O(1)

pop()
队首元素(堆顶元素)出队

empty()
检测优先队列是否为空,时间复杂度O(1)

size()
返回优先队列元素个数,时间复杂度O(1)

priority_queue<int> q1;  //大根堆
priority_queue<int, vector<int>, less<int>> q2;  //大根堆
priority_queue<int, vector<int>, greater<int>> q3;   // 小根堆

Code

超时代码:

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long int ll;
const ll N = 4e6 + 10;
const ll NN = 1e7+5;
const ll INF = 0x7fffffff;
ll  k[N],p[N];
int main() {
	ll n,m;
	while(~scanf("%lld%lld",&n,&m)) {
		if(n==0&&m==0) {
			break;
		}
		for(int i=0; i<n; i++) {
			cin>>k[i];
		}
		sort(k,k+n,cmp);
		if(n<m) {
			for(int i=0; i<n; i++) {
				if(i!=n-1)cout<<k[i]<<" ";
				else cout<<k[i];
			}
			cout<<endl;
		} else {
			for(int i=0; i<m; i++) {
				if(i!=n-1)cout<<k[i]<<" ";
				else cout<<k[i];
			}
			cout<<endl;
		}
	}
	return 0;
}

正解:

#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
#define endl '\n'
typedef long long int ll;
const ll N = 4e6 + 10;
const ll NN = 1e7+5;
const ll INF = 0x7fffffff;
ll  k[N],p[N];
ll cmp(ll a,ll b) {
	return a>b;
}
int main() {
	int n,m,t;
	while(~scanf("%d%d",&n,&m)) {
		priority_queue<int> q;
		if(n==0&&m==0)
			break;
		for(int i=0; i<n; i++) {
			scanf("%d",&t);
			q.push(t);
		}
		m=min(n,m);
		for(int i=0; i<m; i++) {
			if(i!=0)
				printf(" ");
			int tmp=q.top() ;
			printf("%d",tmp);
			q.pop();
		}
		printf("\n");
	}
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值