开始的思路是将A+B枚举,然后二分求X-A-B,这样超时了。
后来发现了一种更加巧妙的思路:先将A+B求和后排序,然后二分求X-c,此处将高效的二分用于求数量更大的A+B。果然换个角度,效率提高了N倍。
#include <stdio.h>
#include <algorithm>
#define maxn 500
using namespace std;
__int64 a[maxn],b[maxn],c[maxn],hun[maxn*maxn];
__int64 L,N,M,num;
bool bs(__int64 v)
{
__int64 l,r,m;
l=0;r=num;
while(l<r)
{
m=(l+r)>>1;
if(hun[m]==v) return true;
if(hun[m]<v) l=m+1;
else r=m;
}
return false;
}
bool search(__int64 x)
{
__int64 i,j,k,t;
for(i=0;i<M;i++)
{
t=x-c[i];
if(t<hun[0] || t>hun[num-1]) continue;
if(bs(t))
return true;
}
return false;
}
int main()
{
__int64 i,j,Q,X,ncase=1;
while(scanf("%I64d%I64d%I64d",&L,&N,&M)==3)
{
for(i=0;i<L;i++)
scanf("%I64d",&a[i]);
for(i=0;i<N;i++)
scanf("%I64d",&b[i]);
for(i=0;i<M;i++)
scanf("%I64d",&c[i]);
num=0;
for(i=0;i<L;i++)
for(j=0;j<N;j++)
{
hun[num++]=a[i]+b[j];
}
sort(hun,hun+num);
sort(c,c+M);
scanf("%I64d",&Q);
printf("Case %I64d:\n",ncase++);
while(Q--)
{
scanf("%I64d",&X);
if(X>hun[num-1]+c[M-1] || X<hun[0]+c[0]){
printf("NO\n");
continue;
}
if(search(X))
printf("YES\n");
else printf("NO\n");
}
}
}