Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 6206 Accepted Submission(s): 1732
Problem Description
Hassan is in trouble. His mathematics teacher has given him a very difficult problem called 5-sum. Please help him.
The 5-sum problem is defined as follows: Given 5 sets S_1,...,S_5 of n integer numbers each, is there a_1 in S_1,...,a_5 in S_5 such that a_1+...+a_5=0?
Input
First line of input contains a single integer N (1≤N≤50). N test-cases follow. First line of each test-case contains a single integer n (1<=n<=200). 5 lines follow each containing n integer numbers in range [-10^15, 1 0^15]. I-th line denotes set S_i for 1<=i<=5.
Output
For each test-case output "Yes" (without quotes) if there are a_1 in S_1,...,a_5 in S_5 such that a_1+...+a_5=0, otherwise output "No".
Sample Input
Sample Output
Source
|
题目分析:一开始的想法是五个集合分成三个联合和两个联合,然后二分三个联合的,枚举两个联合的。然后超内存了。。。
然后想到分成2,2,1.枚举第三个集合,在前面两个集合中找第三个集合中元素的相反数x(因为五个数加起来等于0),就可以用尺取法。声明两个指针,先给前两个集合排好序,然后一个指针指向第一个集合中的最大值,第二个指针指向第二个集合中的最小值,如果两个指针指的数之和比x大的话,把指向最小值的那个指针往使数增大的方向移动,如果数之和小于x的话,把指向最大值的那个指针往使数小的方向移动。
代码:注意Longlong
/* Author:kzl */
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef long long LL;
const int maxx = 205;
LL a[5][maxx];
LL cun[maxx * maxx];
LL ch[maxx*maxx];
int t,n;
int main(){
while(scanf("%d",&t)!=EOF)
{
while(t--){
scanf("%d",&n);
for(int j=0;j<5;j++)
for(int i=0;i<n;i++){
scanf("%lld",&a[j][i]);
}
int kk=0,jj = 0;
for(int i=0;i<n;i++)for(int j=0;j<n;j++)cun[kk++] = a[0][i]+a[1][j];
for(int i=0;i<n;i++)for(int j=0;j<n;j++)ch[jj++] = a[2][i]+a[3][j];
sort(cun,cun+kk);
sort(ch,ch+jj);
bool flag = false;
for(int i=0;i<n;i++){
int xx = 0,yy = jj-1;
LL val = -a[4][i];
while(xx<kk&&yy>=0){
if(cun[xx]+ch[yy]>val)yy--;
else if(cun[xx]+ch[yy]<val)xx++;
else {flag = true;break;}
}
if(flag)break;
}
if(flag)printf("Yes\n");
else printf("No\n");
}
}
return 0;
}