1.题目描述:点击打开链接
2.解题思路:本题要求从4个集合中分别找4个数,使他们的和相加等于0的所有情况个数,由于每个元素的范围比较大,且一个集合的总量可以多达4000,直接写四重循环肯定TLE,需要优化,由a+b+c+d=0移项得a+b=-c-d,因此可以事先分别统计所有的a+b,-c-d的值到s,t数组中,排好序后在t数组中找s中的每一个元素,此时可以直接用upper_bound,lower_bound的差得到c,d的方案数,注意:由于s中可能有重复的元素,因此要记得加上第一次找到的c,d的方案数。总时间复杂度是O(n2*logn)
3.代码:
#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<algorithm> #include<string> #include<sstream> #include<set> #include<vector> #include<stack> #include<map> #include<queue> #include<cstdlib> #include<cstdio> #include<cstring> #include<cmath> #include<ctime> using namespace std; const int maxn = 4000 + 100; int A[maxn], B[maxn], C[maxn], D[maxn]; int s[maxn*maxn], t[maxn*maxn]; int main() { //freopen("test.txt", "r", stdin); int T; int n; scanf("%d", &T); while (T--) { memset(s, 0, sizeof(s)); memset(t, 0, sizeof(t)); scanf("%d", &n); 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++) { s[(i - 1)*n + j] = A[i] + B[j]; t[(i - 1)*n + j] = C[i] + D[j]; } sort(s + 1, s + n*n + 1); sort(t + 1, t + n*n + 1); long long ans = 0; int k1, k2; s[0] = -999999999; for (int i = 1; i <= n*n; i++) { if (s[i] == s[i - 1])//如果有重复项,说明有其他的两个数也得到相同的和,此时要累加原来的解的个数 { ans += (k2 - k1); continue; } k1 = lower_bound(t + 1, t + n*n + 1, (-s[i])) - t;//查找相反数的下界 k2 = upper_bound(t + 1, t + n*n + 1, (-s[i])) - t;//查找相反数的上界 ans += (k2 - k1); } printf("%lld\n", ans); if (T)printf("\n"); } return 0; }