题目描述
有两个长度都是N的序列A和B,在A和B中各取一个数相加可以得到N^2个和,求这N^2个和中最小的N个。
输入输出格式
输入格式:
第一行一个正整数N;
第二行N个整数A_iAi, 满足A_i\le A_{i+1}Ai≤Ai+1且A_i\le 10^9Ai≤109;
第三行N个整数B_iBi, 满足B_i\le B_{i+1}Bi≤Bi+1且B_i\le 10^9Bi≤109.
【数据规模】
对于50%的数据中,满足1<=N<=1000;
对于100%的数据中,满足1<=N<=100000。
输出格式:
输出仅一行,包含N个整数,从小到大输出这N个最小的和,相邻数字之间用空格隔开。
输入输出样例
输入样例#1
3 2 6 6 1 4 8
输出样例#1
3 6 7
思路
一个个都用堆?我用的二分答案,把答案在n^2个数里逐排比较,遇到大于答案或者超过n个数的就break,最后再排序,输出n个即可。
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
int a[110001],b[110001],sq[6000001],n,s;
inline int judge(int x)
{
register int i,j,sum(0);
for(i=1;i<=n;i++)
{
if(sum>n || a[i]+b[1]>x) break;
for(j=1;j<=n;j++)
{
if(a[i]+b[j]<x)
{
sum++;
if(sum>n) break;
}
if(a[i]+b[j]>x) break;
}
}
if(sum>=n) return 1;
else return 0;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
register int i,j;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>a[i];
}
for(i=1;i<=n;i++)
{
cin>>b[i];
}
int l=a[1]+b[1],r=a[n]+b[n];
while(r!=l)
{
int mid=(l+r)/2;
if(judge(mid)==1)
{
r=mid;
}
else
{
l=mid+1;
}
}
l--;
for(i=1;i<=n;i++)
{
if(a[i]+b[1]>l) break;
for(j=1;j<=n;j++)
{
if(a[i]+b[j]>l) break;
else
{
s++;
sq[s]=a[i]+b[j];
}
}
}
sort(sq+1,sq+s+1);
for(i=1;i<=n;i++)
{
cout<<sq[i]<<' ';
}
cout<<endl;
return 0;
}