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).
好多时候,我们把东西分为两个是最好的,因为当我们枚举一种的时候,另一种的情况我们可以直接从sum-x直接得到。好多题目,都是利用这个思想来简化时间复杂度, 【某两种的总和为定值时候】。
分析,我们可以将前两个集合的所有情况分为一组X,把后两个集合的所有情况分为一组Y,然后枚举一个组X,二分另一个组。时间复杂度o(n*nlogn) 空间复杂度 n^2
代码
#include<cstdio>
#include<algorithm>
using namespace std;
#define LL long long
const int MAXN = 4000+5;
const int MAXM = 2e7;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;
int a[MAXN],b[MAXN],c[MAXN],d[MAXN];
int x[MAXM],y[MAXM];
int main(){
int n;scanf("%d",&n);
int cnt1=0;int cnt2=0;
for(int i=1;i<=n;i++) {
scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++) {
x[cnt1++]=a[j]+b[i];
y[cnt2++]=c[j]+d[i];
}
}
sort(y,y+cnt2);
LL ans=0;
for(int i=0;i<cnt1;i++){
int pos1=lower_bound(y,y+cnt2,-x[i])-y;
int pos2=upper_bound(y,y+cnt2,-x[i])-y;
ans+=pos2-pos1;
}
printf("%lld\n",ans);
return 0;
}