题目描述
有两个从小到大排好序的序号a和b,长度均为n。
要求选择两个数i、j,满足a[i]+b[j]<=m的情况令a[i]+b[j]尽可能大。输出a[i]+b[j]的最大值
输入
输入一个正整数n、m,表示数组的长度、m如上面题面所说 。
第2行输入a数组。
第3行输入b数组。
输出
输出答案。
样例输入
复制样例数据
4 10 1 3 5 9 2 8 9 10
样例输出
10
提示
100%的数据满足:1 ≤ n ≤ 1,000,000.
所有数保证大小∈[1,1000000000].
题干含有如下关键条件:
- 两个数组都是有序的。
- 从a[i]中选择一个数,再从b[j]中选择一个数。
- m内尽可能大。
- 两个数组的长度最大为1e6。
用最朴素的算法就是对于每一个a[i],都要遍历一遍b[i]来判断一下a[i]+b[j]与m的关系。是O(n^2)的复杂度,极限数据为复杂度为1e12,显然大量超时。
根据题目中有序的条件,我们可以把某一个循环优化为二分查找,这样极限复杂度被降为了1e6*log2(1e6),在1.8e7~2.4e7之间。满足了时间复杂度的限制。
#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
#include <algorithm>
#include <iomanip>
#include <cstring>
#include <cmath>
//#include <minmax.h>
#define DETERMINATION main
#define lldin(a) scanf("%lld",&a)
#define din(a) scanf("%d",&a)
#define reset(a,b) memset(a,b,sizeof(a))
const int INF=0x3f3f3f3f;
const int LIM=1e7+356;
using namespace std;
typedef long long ll;
/**you can feel the pulse of your destiny...
The nervous feeling fills you with determination.**/
int a[LIM],b[LIM];
int DETERMINATION()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
cin>>b[i];
int ans=0;
int l=1,r=n;
for(int i=1;i<=n;i++)//第一个循环采用朴素遍历
{
l=1,r=n;
while(l<=r)//第二个循环优化为二分查找
{
int mid=(l+r)>>1;
if(b[mid]+a[i]<=m)
{
ans=max(a[i]+b[mid],ans);
l=mid+1;
}
else
{
r=mid-1;
}
}
}
cout<<ans<<endl;
return 0;
}