Trouble HDU - 4334


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
      
      
2 2 1 -1 1 -1 1 -1 1 -1 1 -1 3 1 2 3 -1 -2 -3 4 5 6 -1 3 2 -4 -10 -1
 

Sample Output
      
      
No Yes
 

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值