4 Values whose Sum is 0
题目
本题链接
Time Limit:15000MS Memory Limit:228000KB
- 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).
分析
显而易见四组数据一一枚举肯定会超时,故本题应采用二分法,将四组数据分别合并成两组数据的和(两个4000*4000数组),进行排序,去重,可二分查找到结果并输出,另外本题也可采用hash做法。
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int a[4005];
int b[4005];
int c[4005];
int d[4005];
int tmp1[16000005];
int tmp2[16000005];
int re1[16000005][2];
int re2[16000005][2];
int bs(int key, int num)
{
int lo=0,hi=num;
int mi;
while(lo<=hi)
{
mi=((hi-lo)>>1)+lo;
if(re1[mi][0]==key) return mi;
else if(re1[mi][0]<key) lo=mi+1;
else hi=mi-1;
}
return -1;
}
int main()
{
int n;
int cnt1 = 0, cnt2 = 0;
int sum = 0;
scanf("%d",&n);
for(int i=0; i<n; i++)
scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
for(int i=0; i<n; i++)
for(int j=0; j<n; j++){
tmp1[i*n+j] = a[i] + b[j];
tmp2[i*n+j] = c[i] + d[j];
}
sort(tmp1,tmp1+n*n);
sort(tmp2,tmp2+n*n);
re1[0][0] = tmp1[0];
re2[0][0] = tmp2[0];
for(int i=1; i<n*n; i++)
{
if(tmp1[i-1] != tmp1[i])
{
cnt1++;
re1[cnt1][0] = tmp1[i];
}
else if(tmp1[i-1] == tmp1[i])
{
re1[cnt1][1]++;
}
if(tmp2[i-1] != tmp2[i])
{
cnt2++;
re2[cnt2][0] = tmp2[i];
}
else if(tmp2[i-1] == tmp2[i])
{
re2[cnt2][1]++;
}
}
for(int i=0; i<cnt2+1; i++)
{
int t = bs(-re2[i][0],cnt1);
if(t+1)
sum += (re2[i][1]+1) * (re1[t][1]+1);
}
printf("%d\n", sum);
return 0;
}