7/21 A 解题报告
A题是说三个序列ABC,每个都有很多数,从每个序列中找出一个数相加等于给定的X。
这和紫书中的一个题类似,书上是4个集合找4个数相加为0。
基本方法就是把两个序列相加合并为一个和的集合,之后对这个集合排序并二分查找就有了。最终是nlogn的复杂度。如果二分的是另一个序列,则复杂度是n²logn,肯定不划算。
以下是代码(可直接AC):
#include <iostream>
#include <algorithm>
using namespace std;
int tmp[250000];
int comp(const void*a,const void*b)
{
return *(int*)a-*(int*)b;
}
int main()
{
int l,n,m,a[500],b[500],c[500],k,ca=0,p;
int x,y,z;
int low,high,mid;
bool flag,quit,con;
while(cin>>l>>n>>m)
{
x=y=z=0;
for(int i=0;i<l;i++)
cin>>a[i];
for(int i=0;i<m;i++)
cin>>b[i];
for(int i=0;i<n;i++)
cin>>c[i];
cin>>p;
x=0;
for(int j=0;j<l;j++)
{
for(int u=0;u<n;u++)
{
tmp[x++]=a[j]+b[u];//合并AB
}
}
qsort(tmp,l*n,sizeof(int),comp);
cout<<"Case "<<++ca<<":"<<endl;
for(int i=0;i<p;i++)
{
quit=false;
flag=false;
con=true;
low=-1;high=m;
mid=(low+high)/2;
cin>>k;
for(int j=0;j<m&&!quit;j++)//对C集合每个元素
{
low=-1;high=l*n;//为了边界可以取
mid=(low+high)/2;
while(low<high-1)//二分
{
if(tmp[mid]+c[j]==k)
{
quit=true;
flag=true;
cout<<"YES\n";
break;
}else{
if(tmp[mid]+c[j]>k)
{
high=mid;
mid=(low+high)/2;
}else{
low=mid;
mid=(low+high)/2;
}
}
}
}
if(!flag)
cout<<"NO\n";
}
}
return 0;
}