icodelab 有序表的最小和

描述

给出两个长度为 n 的有序表 A 和 B,在 A 和 B 中各任取一个元素,可以得到 n^2 个和,求这些和中最小的 n 个。

输入

第 1 行包含 1 个整数正 n(n≤400000)。第 2 行与第 3 行分别有 n 个整数,各代表有序表 A 和 B。一行中的每两个整数之间用一个空格隔开,大小在长整型范围内,数据保证有序表单调递增。

输出

输出共 n 行,每行一个整数,第 i 行为第 i 小的和。数据保证在 long long 范围内。

输入样例 1

3
1 2 5
2 4 7

输出样例 1

3
4
5

思路

用优先队列水过了。。。

只需要建一个大根堆,初始的值用第一个元素和另一个队列挨个加一波,之后每次拿后一个元素与另一个队列的元素相加,如果比队首的值小,就弹出队首,加入新元素,当加的值比队首大时,就进入下一次比较。

代码

#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int N=400010;

int n,a[N],b[N],c[N];

priority_queue<int> ans;

int main () {
	scanf("%d",&n);
	for(int i=1; i<=n; i++)
		scanf("%d",&a[i]);
	for(int i=1; i<=n; i++) {
		scanf("%d",&b[i]);
		ans.push(a[1]+b[i]);
	}
	for(int i=2; i<=n; i++)
		for(int j=1; j<=n; j++) {
			if(a[i]+b[j]>ans.top())
				break;
			if(a[i]+b[j]<ans.top()) {
				ans.pop();
				ans.push(a[i]+b[j]);
			}
		}
	for(int i=1; i<=n; i++) {
		c[i]=ans.top();
		ans.pop();
	}
	for(int i=n; i>=1; i--)
		printf("%d\n",c[i]);
	return 0;
}

猜你喜欢

转载自www.cnblogs.com/mysh/p/11312564.html