Wiki OI 1245 最小的N个和

题目链接:http://wikioi.com/problem/1245/

算法与思路:K路归并 + 堆(优先队列),K路归并具体请参考刘汝佳《算法竞赛入门经典训练指南》P189;

题目要求从两个长度为n的数列中各取出一数相加,可得到n*n个和,输出这些和升序的前n项;

由于数据太大,不能通过先求和再排序的方式来求解,这个时候就要用到堆了;

首先将a,b两数组排序,然后将a[i] + b[1]压入堆中,设每次出堆的元素为sum = a[a] + b[b],

则将a[a] + b[b + 1]入堆,这样可以保证前n个出堆的元素为最小的n项;在实现的时候,

可以不用保存b数组的下标,通过sum - b[b] + b[b + 1]来替换a[a] + b[b + 1]来节省空间。

#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
const int N = 100005;
struct node
{
	int sum;
	int b;
	bool operator < (node a) const
	{
		return sum > a.sum;
	}
}heap[N * 2];
priority_queue<node>q;
int cmp(int x, int y)
{
	return x < y;
}
int main()
{
	int n, a[N], b[N], i;
	scanf("%d", &n);
	for(i = 1; i <= n; i++)
	    scanf("%d", &a[i]);
	for(i = 1; i <= n; i++)
	    scanf("%d", &b[i]);
	sort(a + 1, a + n + 1, cmp);
	sort(b + 1, b + n + 1, cmp);
	for(i = 1; i <= n; i++)
		q.push((node){a[i] + b[1], 1});
	for(i = 1; i <= n; i++) 
	{
		node buf = q.top();
		q.pop();
		printf("%d ", buf.sum);
		if(buf.b <= n)
		    q.push((node){buf.sum - b[buf.b] + b[buf.b + 1], buf.b + 1}); 
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值