序列合并
题目描述
有两个长度为 N N N 的单调不降序列 A , B A,B A,B,在 A , B A,B A,B 中各取一个数相加可以得到 N 2 N^2 N2 个和,求这 N 2 N^2 N2 个和中最小的 N N N 个。
输入格式
第一行一个正整数 N N N;
第二行 N N N 个整数 A 1 … N A_{1\dots N} A1…N。
第三行 N N N 个整数 B 1 … N B_{1\dots N} B1…N。
输出格式
一行 N N N 个整数,从小到大表示这 N N N 个最小的和。
样例 #1
样例输入 #1
3
2 6 6
1 4 8
样例输出 #1
3 6 7
提示
对于 50 % 50\% 50% 的数据, N ≤ 1 0 3 N \le 10^3 N≤103。
对于 100 % 100\% 100% 的数据, 1 ≤ N ≤ 1 0 5 1 \le N \le 10^5 1≤N≤105, 1 ≤ a i , b i ≤ 1 0 9 1 \le a_i,b_i \le 10^9 1≤ai,bi≤109。
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
const int N=1e5+10;
using namespace std;
vector <int> a;
vector <int> b;
priority_queue<int>q;//这里必须要默认从小到大排序,否则获取的top是最小值无法与后面算的值比较
int main()
{
int n;
cin>>n;
int x;
for(int i=0;i<n;i++)
{
cin>>x;
a.push_back(x);
}
sort(a.begin(),a.end());
for(int i=0;i<n;i++)
{
cin>>x;
b.push_back(x);
}
sort(b.begin(),b.end());
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
auto v=a[i]+b[j];
if(q.size()<n)//我们只要n个数
{
q.push(v);
}
else//有了n个数,还要判断这n个数是不是最小的
{
if(q.top()>v)//因为优先队列默认从小到大排序,所以队列顶端top是最大值,如果最大值比新的值大,我们删除top值增加v
{
q.pop();
q.push(v);
}
else//如果最大值小于当前这个v,那么b数组后面的都不用加了,因为a,b都是排序了的,越往后面越大,我们不需要大的值
break;
}
}
}
int ans[N];
for(int i=n-1;i>=0;i--)
{
ans[i]=q.top();//队列是从小到大排序的,top是最大值,先存入数组中
q.pop();
}
for(int i=0;i<n;i++)//反向输出
{
cout<<ans[i]<<" ";
}
return 0;
}```