PS/BOJ2022. 5. 5. 13:30

합이 0인 네 정수 : https://www.acmicpc.net/problem/7453

참조 : https://loosie.tistory.com/553

 

문제 풀이가 안되어 참조 포스팅의 내용을 스터디할 목적으로 작성된 코드.

이번에도 배열을 두개로 나누어 부분합을 구함( a와b를 1:1 , b와c를 1:1)

N*N => 4000*4000으로 int로 넉넉함.

 

입력값이 2^28로 4개 요소를 더하면 overflow 발생.

값을 연산하기 위해 long으로 사용해야한다.

 

cnt의 경우도 N^4까지 발생할 수 있으므로 long을 취해야한다.

cnt계산 시 중복을 처리하는 방법을 생각해낸 사람은 정말 대단한 것 같다.

 

//refer : https://loosie.tistory.com/553
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {

	static int N;
	static int[][] abcd;
	static int[] ab, cd;
	static boolean DBG = false;


	public static void main(String[] args) throws IOException {

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());

		N = Integer.parseInt(st.nextToken());

		abcd = new int[N][4];

		for (int i = 0; i < N; i++) {
			st = new StringTokenizer(br.readLine());

			for (int j = 0; j < 4; j++) {
				abcd[i][j] = Integer.parseInt(st.nextToken());
			}
		}

		ab = new int[N * N];// 1:1 matching
		cd = new int[N * N];// 1:1 matching

		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				ab[i * N + j] = abcd[i][0] + abcd[j][1];
				cd[i * N + j] = abcd[i][2] + abcd[j][3];
			}
		}

		Arrays.sort(ab);
		Arrays.sort(cd);

		if (DBG) {
			for (int v : ab)
				System.out.print(v + " ");
			System.out.println();
			for (int v : cd)
				System.out.print(v + " ");
			System.out.println();
		}
		
		int abp=0,cdp=N*N-1;
		long cnt =0;
		
		while (abp <N*N && cdp>-1) {

			
			long abv = ab[abp], cdv=cd[cdp];
			long sum=abv+cdv;
			if( sum < 0) {
				abp++;
			} else if( sum > 0) {
				cdp--;
			} else {
				
				long abCnt=0,cdCnt=0;
				
				while(abp<N*N && abv == ab[abp]) {
					abp++;
					abCnt++;
				}
				while(cdp>-1 && cdv == cd[cdp]) {
					cdp--;
					cdCnt++;
				}
				
				cnt += abCnt * cdCnt;
				
				//System.out.printf("cnt : %d\n",cnt);
			}
			
		}
		System.out.println(cnt);
		
		
	}

}

 

 

아래와 같이 two points 로만 탐색하면 중복에 대한 처리가 제대로 카운팅되지 않는다.

같은 값의 요소들은 서로 1:1로 매핑되어 세어줘야한다.

		while (abp <N*N && cdp>-1) {

			
			int abv = ab[abp], cdv=cd[cdp];
			long sum=abv+cdv;
			if( sum < 0) {
				abp++;
			} else if( sum > 0) {
				cdp--;
			} else {
				cnt++;
				abp++;
				//System.out.printf("cnt : %d\n",cnt);
			}
			
		}

 

'PS > BOJ' 카테고리의 다른 글

2143 (두 배열의 합, 중요)  (0) 2022.05.05
2632  (0) 2022.05.05
1208 이진 탐색 : upper_bound 및 lower_bound 찾기  (0) 2022.05.05
부분 수열 DFS 기본형태  (0) 2022.05.05
1208  (0) 2022.05.05
Posted by easy16