문제 링크](https://www.acmicpc.net/problem/7453)
메모리: 161996 KB, 시간: 4392 ms
이분 탐색, 중간에서 만나기, 정렬, 두 포인터
2025년 1월 21일 15:51:39
정수로 이루어진 크기가 같은 배열 A, B, C, D가 있다.
A[a], B[b], C[c], D[d]의 합이 0인 (a, b, c, d) 쌍의 개수를 구하는 프로그램을 작성하시오.
첫째 줄에 배열의 크기 n (1 ≤ n ≤ 4000)이 주어진다. 다음 n개 줄에는 A, B, C, D에 포함되는 정수가 공백으로 구분되어져서 주어진다. 배열에 들어있는 정수의 절댓값은 최대 228이다.
합이 0이 되는 쌍의 개수를 출력한다.
/**
* Author: yngbao97, Yuk Yejin
* Problem: 합이 0인 네 정수_7453
* Date: 2025.01.21
*/
import java.util.*;
import java.lang.*;
import java.io.*;
public class Main {
static BufferedReader br;
static BufferedWriter bw;
static StringTokenizer st;
public static void main(String[] args) throws Exception {
br = new BufferedReader(new InputStreamReader(System.in));
bw = new BufferedWriter(new OutputStreamWriter(System.out));
int n = Integer.parseInt(br.readLine());
int[] A = new int[n];
int[] B = new int[n];
int[] C = new int[n];
int[] D = new int[n];
for (int i = 0; i < n; i++) {
st = new StringTokenizer(br.readLine(), " ");
A[i] = Integer.parseInt(st.nextToken());
B[i] = Integer.parseInt(st.nextToken());
C[i] = Integer.parseInt(st.nextToken());
D[i] = Integer.parseInt(st.nextToken());
}
int[] AB = new int[n*n];
int[] CD = new int[n*n];
int idx = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
AB[idx] = A[i] + B[j];
CD[idx++] = C[i] + D[j];
}
}
Arrays.sort(AB);
Arrays.sort(CD);
long answer = 0;
int abIdx = 0;
int cdIdx = n*n - 1;
while (abIdx < n*n && cdIdx >= 0) {
int gap = AB[abIdx] + CD[cdIdx];
if (gap > 0) cdIdx--;
else if (gap < 0) abIdx++;
else {
long abCnt = 0;
long cdCnt = 0;
int ab = AB[abIdx];
int cd = CD[cdIdx];
while (abIdx < n*n && AB[abIdx] == ab) {
abCnt++;
abIdx++;
}
while (cdIdx >= 0 && CD[cdIdx] == cd) {
cdCnt++;
cdIdx--;
}
answer += abCnt * cdCnt;
}
}
bw.write(String.valueOf(answer));
bw.flush();
bw.close();
br.close();
}
}