时间限制: 3 Sec 内存限制: 256 MB
提交: 621 解决: 62
[提交][状态][讨论版][命题人:外部导入]
题目描述
有两个长度为N的序列A和B,在A和B中各任取一个数相加可以得到N2个和,求这N2个和中最小的N个。
输入
第一行输入一个正整数N(1<=N<=100000);
第二行N个整数Ai且Ai<=109;第三行N个整数Bi且Bi<=109。
输出
输出仅一行,包含n个整数,从小到大输出这n个最小的和,相邻数字之间用空格隔开。
样例输入
5
1 3 2 4 5
6 3 4 1 7
样例输出
2 3 4 4 5
按大白书上的原理,先对两个数组排序,用一个二元组来标记两个数的和,和b数组的当前位置,放入优先队列中。每一次把最小的取出来,再把最小和s-b[i]+b[i+1]放入队列,循环n次就可以了;
#include<stack> #include<queue> #include<math.h> #include<vector> #include<string> #include<stdio.h> #include<iostream> #include<string.h> #include<algorithm> #include<map> #define maxn 5000005 #define mem(a,b) memset(a,b,sizeof(a)) #define ll long long #define inf 0x3f3f3f using namespace std; ll a[maxn]; ll b[maxn]; ll c[maxn]; struct node{ ll s,b; node(ll s,ll b):s(s),b(b){} bool operator <(const node& rhs)const{ return s>rhs.s; } }; void m(ll *A,ll *B,ll *C,int n){ priority_queue<node>q; for(int i=0;i<n;i++){ q.push(node(A[i]+B[0],0)); } for(int i=0;i<n;i++){ node d=q.top();q.pop(); C[i]=d.s; int b=d.b; if(b+1<n)q.push(node(d.s-B[b]+B[b+1],b+1)); } } int main(){ int n; while(~scanf("%d",&n)){ for(int i=0;i<n;i++)scanf("%lld",&a[i]); for(int j=0;j<n;j++)scanf("%lld",&b[j]); sort(a,a+n); sort(b,b+n); m(a,b,c,n); for(int i=0;i<n;i++){ cout<<c[i]<<" "; } } }