题目描述 Description
有两个长度为 N 的序列 A 和 B,在 A 和 B 中各任取一个数可以得到 N^2 个和,求这N^2 个和中最小的 N个。
输入描述 Input Description
第一行输入一个正整数N;第二行N个整数Ai 且Ai≤10^9;第三行N个整数Bi,
且Bi≤10^9
输出描述 Output Description
输出仅一行,包含 n 个整数,从小到大输出这 N个最小的和,相邻数字之间用
空格隔开。
样例输入 Sample Input
5
1 3 2 4 5
6 3 4 1 7
样例输出 Sample Output
2 3 4 4 5
数据范围及提示 Data Size & Hint
【数据规模】 对于 100%的数据,满足 1≤N≤100000。
题解:将两个序列按从小到大排序(实际数据已经有序),对于A[i]和B[j],a[i]+b[j]<a[i]+b[j+1]必然成立。
于是我们建一个大根堆,保存最小的N个和。先将A[1]和B的和放入堆中,之后的A[I]和B[J]的和每次与堆顶比较,大于则直接break,小于则置换堆顶即可。输出时逆序输出堆中元素
#include<queue>
#include<cstdio>
#include<iostream>
#define MAXN 1000000
using namespace std;
priority_queue<int> heap;
int n;
int a[MAXN+5],b[MAXN+5],ans[MAXN+5];
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]);
for (int i=1;i<=n;i++) heap.push(a[1]+b[i]);
for (int i=2;i<=n;i++)
{
for (int j=1;j<=n;j++)
{
int now=a[i]+b[j];
if (now<heap.top())
{
heap.pop();
heap.push(now);
}
else break;
}
}
for (int i=1;i<=n;i++)
{
ans[i]=heap.top();
heap.pop();
}
for (int i=n;i>=1;i--) printf("%d ",ans[i]);
return 0;
}