2622: 小H的集合(二分法)

题目链接: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;
}

不太懂二分的话可以看看我之前写的这个博客,记住模板就行啦
二分法(整数二分、浮点数二分)

发布了68 篇原创文章 · 获赞 142 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/wmy0217_/article/details/104295093