4 Values whose Sum is 0
Memory limit:228000 kB OS:Linux
Problem Description
The SUM problem can be formulated as follows: given four lists A, B, C, D of integer values, compute how many quadruplet (a, b, c, d ) ∈ A x B x C x D are such that a + b + c + d = 0 . In the following, we assume that all lists have the same size n .
Input
The first line of the input file contains the size of the lists n (this value can be as large as 4000). We then have n lines containing four integer values (with absolute value as large as 2 28 ) that belong respectively to A, B, C and D .
Output
For each input file, your program has to write the number quadruplets whose sum is zero.
Sample Input
6
-45 22 42 -16
-41 -27 56 30
-36 53 -37 77
-36 30 -75 -46
26 -38 -10 62
-32 -54 -6 45
Sample Output
5
Hint
Sample Explanation: Indeed, the sum of the five following quadruplets is zero: (-45, -27, 42, 30), (26, 30, -10, -46), (-32, 22, 56, -46),(-32, 30, -75, 77), (-32, -54, 56, 30).
题意:
从四个数组A,B,C,D中分别抽取一个数,求和,统计和为0的组合数
解题思路:
如果直接使用暴力求解复杂度会达到O(N^4),超时。先将前两个数组求和,后两个数组求和,得到这两个数组所有组合s1[],s2[],只需对num1[]进行排序。
遍历数组s2,在s1中二分查找 -s2[i],找到后还要统计这个数重复出现的次数。
我原来二分找到-s2[i]之后直接遍历s1来统计重复次数,而这样时间复杂度又直接到了O(N^4),超时,后来才想到直接在这个数的前后来找就可以了。
Code:
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=4000+5;
int A[maxn],B[maxn],C[maxn],D[maxn];
int s1[maxn*maxn],s2[maxn*maxn];
int n;
int bs(int x)
{
int lo=0,hi=n*n-1,mid;
while(lo<=hi)
{
mid=((hi-lo)>>1)+lo;
if(s1[mid]==x)
return mid;
else if(s1[mid]<x)
lo=mid+1;
else
hi=mid-1;
}
return -1;
}
int main()
{
while(cin>>n)
{
for(int i=0; i<n; i++)
cin>>A[i]>>B[i]>>C[i]>>D[i];
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++)
{
s1[i*n+j]=A[i]+B[j];
s2[i*n+j]=C[i]+D[j];
}
}
sort(s1,s1+n*n);
int ans=0;
for(int i=0; i<n*n; i++)
{
int pos=bs(-s2[i]);
if(pos!=-1)
{
ans++;
//在前后寻找重复元素
int p=pos-1;
while(p>=0&&s1[p--]==s1[pos])
ans++;
p=pos+1;
while(p<n*n&&s1[p++]==s1[pos])
ans++;
}
}
cout<<ans<<endl;
}
return 0;
}