Can you find it?
Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 32768/10000 K (Java/Others)
Total Submission(s): 6515 Accepted Submission(s): 1706
Problem Description
Give you three sequences of numbers A, B, C, then we give you a number X. Now you need to calculate if you can find the three numbers Ai, Bj, Ck, which satisfy the formula Ai+Bj+Ck = X.
Input
There are many cases. Every data case is described as followed: In the first line there are three integers L, N, M, in the second line there are L integers represent the sequence A, in the third line there are N integers represent the sequences B, in the forth line there are M integers represent the sequence C. In the fifth line there is an integer S represents there are S integers X to be calculated. 1<=L, N, M<=500, 1<=S<=1000. all the integers are 32-integers.
Output
For each case, firstly you have to print the case number as the form "Case d:", then for the S queries, you calculate if the formula can be satisfied or not. If satisfied, you print "YES", otherwise print "NO".
Sample Input
3 3 3
1 2 3
1 2 3
1 2 3
3
1
4
10
Sample Output
Case 1:
NO
YES
NO
斌神讲的二分搜索很好用,二分思想看似简单,要实现起来要注意N多细节,所以,斌神的二分方法是这样实现的,初始的min=0;max=n;而实际的元素最大下标在数组中为n-1,之所以要这么设置,是因为能探测到首末元素,倘若把max=n-1,是无法探测到末元素的。
因为所要搜索的元素可能根本就不在数组元素中,也可能远大于或小于数组中的任意元素,二分查找的最大价值就体现在此,即使无法在队列中找到元素,也要探测到跟该值最接近的元素位置。故,在实现过程中,采取X<=mid,则min=mid反之则反之,结束条件设置为min=mid;这样即可实现以上作用。另外,在每次计算mid时,mid=(max-min)/2+min比较好。
这个题目要注意很多地方,首先就是计算它的时间复杂度,如果采取暴力的话,为500^3>10^8,毫无疑问会超时,但是在实现二分上很有技巧,即先设置一个大数组需大于500^2,来存贮a+b,然后将c与该数组中的元素相加。。。判断是否等于X。
还有要注意的是,题目明确说了所有数都为32位int整数,但其实是故意让你掉以轻心,一个数为Int,不代表相加后不会超出范围,所以保险起见,应用long long来定义,但是根据我实测,大数组定义为int也是可以AC的,这可能是数据问题
还有个要提醒自己的地方就是 输出的时候竟然丢了冒号,WA了两次才发现这个地方。。。真的。。一定要注意细节。
#include <cstdio>
#include <algorithm>
int a[600];
int b[600];
int c[600];
int sum[260000];
int main()
{
int l,m,n,s;
int t=1,x;
while (scanf("%d%d%d",&l,&m,&n)!=EOF)
{
for (int i=0; i<l; i++)
{
scanf("%d",&a[i]);
}
int temp=0;
for (int j=0; j<m; j++)
{
scanf("%d",&b[j]);
for (int y=0;y<l;y++)
{
sum[temp]=a[y]+b[j];
temp++;
}
}
for (int k=0; k<n; k++)
{
scanf("%d",&c[k]);
}
std::sort(sum,sum+l*m);
std::sort(c,c+n);
scanf("%d",&s);
printf("Case ");
printf("%d:\n",t++);
for (int q=0; q<s; q++)
{
int mid;
scanf("%d",&x);
bool ans=false;
for (int w=0;w<n;w++)
{ int max=m*l,min=0;
for (;;)
{
mid=(max-min)/2+min;
if (mid==min) {break;}
if (sum[mid]<=x-c[w])
{
min=mid;
}
else max=mid;
}
if (sum[mid]==(x-c[w]))
{ans=true;break;}
}
if (ans) printf("YES\n");
else printf("NO\n");
}
}
return 0;
}