题面:
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
题意
给出4个长度为n的四个数组A, B, C,D,让你求出所有从A, B, C, D中各取一个数,使得这4个数相加等于0的方案总数
解法
第一次尝试暴力膜,TLE
二分
思路:
用两个n * n的数组sum1, sum2分别存下A和B的所有元素之和还有C和D的所有元素之和,然后枚举sum1里的每个元素,在sum2里二分查找他的负值,如果找到,则说明他们的和为0。
脑子遇到的坑!
惯性思维里二分查找只是判断x在数组a里有没有,但是这道题不能这样做,因为有可能出现不同的C[i] + D[i]组合但是他们的和相同,存在sum2里,这样子如果只判断-sum1[i]是否存在于sum2里的话是不够的,因为sum2里可能有多个-sum1[i],也就是有多种可能,如果单纯判断有没有的话就会漏掉一些情况。所以二分查找完了还需要计数,返回值是sum2里有多少个sum1[i]
代码
#include <stdio.h>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <string>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <ctime>
#include <vector>
#include <list>
#include <iomanip>
#include <numeric>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define ms(s) memset(s, 0, sizeof(s))
#define rep(i, n) for (int i=0; i<(n); i++)
#define Rep(i, n) for (int i=1; i<=(n); i++)
#define range(x) (x).begin(), (x).end()
#define read(x) freopen(x, "r", stdin);
const int inf = 0x3f3f3f3f;
#define maxn 4005
#define LOCAL
long long int a[maxn][4];
long long int b[maxn * maxn];
long long int c[maxn * maxn];
long long int n, t = 0;
//优化之后的二分查找
int binary_search(int a){
int r = t - 1;
int l = 0;
while (r - l >= 1){
int m = (r + l) / 2;
if (c[m] == a){
int ans = 0;
//主要是这里,这里返回的是从l到r出现x的次数,而不是单纯的true
for (int i = l; i <= r; i++){
if (c[i] == a) ans++;
}
return ans;
}
else if (a > c[m]){
l = m + 1;
}
else{
r = m;
}
}
return 0;
}
//打印调试函数
void print(){
printf("t = %d\n", t);
for (int i = 0; i < t; i++){
printf("%lld %lld\n", b[i], c[i]);
}
}
int main(int argc, char * argv[]) {
// freopen("in.txt", "r", stdin);
while (cin >> n){
int temp;
long long int ans = 0;
t = 0;
for (int i = 0; i < n; i++){
//用a[i][0 ~ 3]代替了ABCD
cin >> a[i][0] >> a[i][1] >> a[i][2] >> a[i][3];
}
for (int i = 0; i < n; i++){
for (int j = 0; j < n; j++){
//把每个和存进b和c里
b[t] = a[i][0] + a[j][1];
c[t++] = a[i][2] + a[j][3];
}
}
sort(c, c + t);
for (int i = 0; i < t; i++){
if (temp = binary_search(-b[i])){
//累加返回c里的-b[i]的个数
ans += temp;
}
}
cout << ans << endl;
}
return 0;
}