题意:有5个集合,从这5个集合中各取1个元素,使之和为0,如果存在输出Yes,否则输出No。
假设现在有两个有序序列,有两个指针,一个指向第一个序列的最大值,另一个指向第二个有序序列的最小值,将两个指针所指的值相加,如果小于固定值x,则第二个指针向值更大的方向移动,否则反之。
而这个题是5个集合,可以将1,2看作一组,将3,4看作一组,进行计算。具体的代码如下。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
__int64 a[5][410],b[41000],c[41000];
int n;
int cmp(const void*a,const void*b)
{
if(*(__int64 *)a-*(__int64 *)b > 0)
return 1;
return -1;
}
int find(__int64 x)
{
int i=0,j=n*n-1,flag=0;
while(1)
{
if(i==n*n) break;
if(j==-1) break;
if(b[i]+c[j]>x)
j--;
if(b[i]+c[j]<x)
i++;
if(b[i]+c[j]==x)
{
flag=1;
break;
}
}
if(flag==1) return 1;
else return 0;
}
int main()
{
int t,i,j,k,k1,k2,flag;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
for(i=0;i<5;i++)
{
for(j=0;j<n;j++)
scanf("%I64d",&a[i][j]);
}
k1=0;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
b[k1++]=a[0][i]+a[1][j];
}
}
qsort(b,n*n,sizeof(b[0]),cmp);
k2=0;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
c[k2++]=a[2][i]+a[3][j];
qsort(c,n*n,sizeof(c[0]),cmp);
flag=0;
for(i=0;i<n;i++)
{
if(find(-a[4][i])==1)
{
flag=1;
break;
}
}
if(flag==1) printf("Yes\n");
else printf("No\n");
}
return 0;
}