题目背景
- 洛谷:P1631 序列合并
数据增强版
题目描述
有两个长度都是 N 的序列 A 和 B ,在 A 和 B 中各取一个数相加可以得到 N2 个和,求这 N2 个和中最小的 N 个。
输入格式
第一行一个正整数 N ,满足 1≤N≤1000000
。
第二行 N 个整数 Ai ,满足 Ai≤109 。
第三行 N 个整数 Bi ,满足 Bi≤109 。
输出格式
输出仅一行,包含 N 个整数,从小到大输出这 N 个最小的和,相邻数字之间用空格隔开。
输入输出样例
输入样例
3
2 6 6
1 4 8
输出样例
3 6 7
AC代码与思路
两个数组输入的数不保证有序
。
优先队列
生成一个长度为N的优先队列,该队列由A[i]+B[0]组成(i=0,1,2……,N-1)。若A[ i ]+B[ j ]被取出队列,将A[ i ]+B[ j+1 ]放入队列。按此取出N个元素,该N个元素即为最小的N个元素。
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
#define MaxSize 1000010
typedef struct SumWithFactor
{
int FactorANo;
int FactorBNo;
int Sum;
//优先队列默认大顶堆,改变"<"定义,使其变成小顶堆
bool friend operator<(SumWithFactor Sum1, SumWithFactor Sum2)
{
return Sum1.Sum > Sum2.Sum;
}
} SumWithFactor;
int main()
{
int n;
int NoA, NoB;
int NumSetA[MaxSize] = {0}, NumSetB[MaxSize] = {0};
SumWithFactor Temp;
priority_queue<SumWithFactor> SumList;
//关闭流同步
ios::sync_with_stdio(false);
cin >> n;
for (int i = 0; i < n; ++i)
cin >> NumSetA[i];
for (int i = 0; i < n; ++i)
cin >> NumSetB[i];
//排序
sort(NumSetA, NumSetA + n);
sort(NumSetB, NumSetB + n);
//生成一个长度为n的优先队列
//该队列由A[i]+B[0]组成(i=0,1,2……,n-1)
for (int i = 0; i < n; ++i)
{
Temp.FactorANo = i;
Temp.FactorBNo = 0;
Temp.Sum = NumSetA[i] + NumSetB[0];
SumList.push(Temp);
}
//若A[i]+B[j]被取出队列,将A[i]+B[j+1]放入队列
//按此取出n个元素,该n个元素即为最小的n个元素
for (int i = 0; i < n; ++i)
{
Temp = SumList.top();
cout << Temp.Sum << " "; //注意输出格式
SumList.pop();
++Temp.FactorBNo;
Temp.Sum = NumSetA[Temp.FactorANo] + NumSetB[Temp.FactorBNo];
SumList.push(Temp);
}
return 0;
}