http://acm.tju.edu.cn/toj/showp2407.html
二分,先将前面两个数组的和求出排序,然后是后面两个求和逆序;
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
int n, arr[4010][4];
int b[4010 * 4010], c[4010 * 4010];
int main()
{
while (scanf("%d", &n) != EOF)
{
int i, j, k = 0;
ll re1, re2, sum = 0;
for (i = 0; i < n; i ++)
for (j = 0; j < 4; j ++)
scanf("%d", &arr[i][j]);
for (i = 0; i < n; i ++)
for (j = 0; j < n; j ++)
{
b[k] = arr[i][0] + arr[j][1];
c[k] = arr[i][2] + arr[j][3];
k ++;
}
int N = n * n;
sort(b, b + N);
sort(c, c + N);
for (i = 0, j = N - 1; i < N && j >= 0;)
{
if (b[i] + c[j] > 0) j --;
else if (b[i] + c[j] < 0) i ++;
else
{
re1 = re2 = 1;
while (i + 1 < N && b[i] == b[i + 1])
re1 ++, i ++;
while (j - 1 >= 0 && c[j] == c[j - 1])
re2 ++, j --;
sum += (ll)re1 * re2;
i ++, j --;
}
}
printf("%lld\n", sum);
return 0;
}
}