4 Values whose Sum is 0 (二分)
思路:分治法
枚举4组数O(n^4)绝对超时
因此可以使用分治的思想,将 4 组数分为两组,然后每组再分别计算和,最后对两组合进行排序,让正数与负数相加判断是否为 0 即可
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 6 using namespace std; 7 8 int a[4001]; 9 int b[4001]; 10 int c[4001]; 11 int d[4001]; 12 int n; 13 int s1[20000000]; 14 int s2[20000000]; 15 16 int main() 17 { 18 while(scanf("%d", &n) != EOF) 19 { 20 for(int i = 1; i <=n; ++i) 21 scanf("%d %d %d %d", &a[i], &b[i], &c[i], &d[i]); 22 23 int k = 1; 24 for(int i = 1; i <= n; ++i) 25 { 26 for(int j = 1; j <= n; ++j) 27 { 28 s1[k] = a[i] + b[j]; 29 s2[k] = c[i] + d[j]; 30 ++k; 31 } 32 } 33 34 sort(s1+1, s1+k); 35 sort(s2+1, s2+k); 36 37 int right = k - 1; 38 int ans = 0; 39 for(int left = 1; left < k; ++left) 40 { 41 while(right > 0 && s1[left] + s2[right] > 0) 42 right--; 43 44 if(right < 0) 45 break; 46 47 int tmp = right; // 一组left可能对应多组right解 48 while(right > 0 && s1[left] + s2[right] == 0) 49 { 50 ans++; 51 right--; 52 } 53 right = tmp; // 下一组left可能和当前这一组left相同,所以rigiht要复原 54 } 55 56 printf("%d\n", ans); 57 } 58 59 60 return 0; 61 }