题目描述
有两个长度都是N的序列A和B,在A和B中各取一个数相加可以得到N^2N2个和,求这N^2N2个和中最小的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
二分值
//#include <iostream>
//#include <cstring>
//#include <iomanip>
//#include <algorithm>
//#include <queue>
//#include <stack>
//#include <vector>
//#include <set>
//#include <map>
//#include <cmath>
//#include <cstdio>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef __int128 bll;
const ll maxn = 1e5+100;
const ll mod = 1e9+7;
const ld pi = acos(-1.0);
const ll inf = 1e18;
const ld eps = 1e-5;
const ld e = exp(1);
ll n,a[maxn],b[maxn];
ll ans[maxn],len;
ll check(ll x)
{
ll num = 0;
ll j = n;
for(ll i = 1; i <= n; i++)
{
while(a[i]+b[j] >= x && j >= 1)
{
j--;
}
num += j;
}
return num;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin >> n;
for(ll i = 1; i <= n; i++)
{
cin >> a[i];
}
for(ll i = 1; i <= n; i++)
{
cin >> b[i];
}
sort(a+1,a+1+n);
sort(b+1,b+1+n);
ll l = a[1]+b[1],r = a[n]+b[n];
while(l <= r)
{
ll mid = (l+r)/2;
if(check(mid) <= n)
{
l = mid+1;
}
else
{
r = mid-1;
}
}
l--;
for(ll i = 1; i <= n && a[i] <= l; i++)
{
ll j = 1;
while(a[i]+b[j] <= l && j <= n)
{
ans[++len] = a[i]+b[j];
j++;
}
}
sort(ans+1,ans+1+len);
for(ll i = 1; i <= n; i++)
cout << ans[i] << " ";
cout << endl;
return 0;
}