题目链接:http://acm.zzuli.edu.cn/problem.php?id=2622
题目描述
小Q发现小P和小H各有一个集合,但是小P的集合A和小H的集合B不一样,小P的集合A里有n个整数且无序,小H的集合B里有m个整数且有序,小Q有一个整数k,小Q想在集合A与集合B中找到一个整数使他们相加正好等于k。你能帮助小Q吗?
输入
第一行是三个整数n,m,k,分别表示集合A的大小、集合B的大小、k的值。(0<n<=100000,0<m<=100000,k在int范围内)
第二行是n个整数。代表小P的集合A中的数,每个数唯一(int范围内)
第二行是m个整数。代表小H的集合B中的数,每个数唯一(int范围内)
输出
请输出一行包含两个整数,分别表示集合A中的数与集合B中的数,整数之间有空格。(输入数据保证输出结果唯一)
样例输入 Copy
5 4 34
1 2 3 4 7
10 20 30 40
样例输出 Copy
4 30
这题刚开始我是用两个数组,然后两个for循环嵌套,发现超时了,然后我又换成set,发现没有什么用,因为还是要用到两个for循环,依然超时…就是下面这个错误的代码…
#include<iostream>
#include<set>
using namespace std;
int main()
{
int n,m,k,x;
cin>>n>>m>>k;
set<int> s1,s2;
for(int i=0;i<n;i++)
{
cin>>x;
s1.insert(x);
}
for(int i=0;i<m;i++)
{
cin>>x;
s2.insert(x);
}
set<int>::iterator it1,it2;
for(it1=s1.begin();it1!=s1.end();it1++)
for(it2=s2.begin();it2!=s2.end();it2++)
if(*it1+*it2==k)
cout<<*it1<<" "<<*it2;
return 0;
}
这题关键是在于我们怎么减少比较次数…前几天学了二分,二分每次可以减少一半数据的比较,正好可以用上,下面就是用二分法做的
#include<iostream>
using namespace std;
int a[100005];
int b[100005];
int xxx(int m,int b[],int s)
{
int l=0,r=m-1;
while(l<r)
{
int mid=(l+r)/2;
if(b[mid]>=s) r=mid;
else l=mid+1;
}
if(b[l]!=s)
return -1; //没有找到,返回-1
else
return l; //return r也可以,因为此时l=r
}
int main()
{
int n,m,k,mm,i;
cin>>n>>m>>k;
for(i=0;i<n;i++)
cin>>a[i];
for(i=0;i<m;i++)
cin>>b[i];
for(i=0;i<n;i++)
{
mm=xxx(m,b,k-a[i]);
if(mm!=-1) //如果mm返回-1我们继续循环,继续调用函数
break; //如果不是-1我们结束循环
}
cout<<a[i]<<" "<<b[mm];
return 0;
}
不太懂二分的话可以看看我之前写的这个博客,记住模板就行啦
二分法(整数二分、浮点数二分)