일단 아이디어 자체는 왼쪽에서 포함되는 점의 위치 leftIndex와 오른쪽에서 포함되는 점의 위치 rightIndex를 각각 구한 뒤,

rightIndex - leftIndex + 1 을 하여 구해 보자는 생각이었다.

import java.util.*;
import java.io.*;

public class Main {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());

		int points = Integer.parseInt(st.nextToken());
		int lines = Integer.parseInt(st.nextToken());

		int point[] = new int[points];

		st = new StringTokenizer(br.readLine());
		for (int i = 0; i < points; i++) {
			point[i] = Integer.parseInt(st.nextToken());
		}
		Arrays.sort(point);

		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		for (int i = 0; i < lines; i++) {
			st = new StringTokenizer(br.readLine());
			int left = Integer.parseInt(st.nextToken());
			int right = Integer.parseInt(st.nextToken());

			int rightIndex = getRightIndex(right, points - 1, point);
			int leftIndex = getLeftIndex(left, points - 1, point);
			// System.out.println(leftIndex + " " + rightIndex);
			int sum = rightIndex - leftIndex + 1;
			sum = Math.max(0, sum);
			bw.write(sum + "\n");
		}
		bw.flush();
		br.close();
	}

	private static int getLeftIndex(int target, int length, int[] point) {
		int start = 0;
		int end = length;
		int answer = end;

		while (start <= end) {
			int mid = (start + end) / 2;

			if (target < point[mid]) {
				answer = Math.min(answer, mid);
				end = mid - 1;
			} else if (target == point[mid]) {
				return mid;
			} else {
				start = mid + 1;
			}
		}
		return answer;
	}

	private static int getRightIndex(int target, int length, int[] point) {
		int start = 0;
		int end = length;
		int answer = 0;

		while (start <= end) {
			int mid = (start + end) / 2;

			if (point[mid] < target) {
				answer = Math.max(answer, mid);
				start = mid + 1;
			} else if (point[mid] == target) {
				return mid;
			} else {
				end = mid - 1;
			}
		}
		return answer;
	}
}

 

하지만, 0이나 40과 같이 범위를 벗어나는 선분인 경우 따로 처리가 필요했다.

(예를 들어 선분 40 40 의 경우 기존 코드에서는 범위에 벗어난 선분이지만 점 1개를 리턴하고 있었다.)

import java.util.*;
import java.io.*;

public class Main {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());

		int points = Integer.parseInt(st.nextToken());
		int lines = Integer.parseInt(st.nextToken());

		int point[] = new int[points];

		st = new StringTokenizer(br.readLine());
		for (int i = 0; i < points; i++) {
			point[i] = Integer.parseInt(st.nextToken());
		}
		Arrays.sort(point);

		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		for (int i = 0; i < lines; i++) {
			st = new StringTokenizer(br.readLine());
			int left = Integer.parseInt(st.nextToken());
			int right = Integer.parseInt(st.nextToken());

			int rightIndex = getRightIndex(right, points - 1, point);
			int leftIndex = getLeftIndex(left, points - 1, point);
			// System.out.println(leftIndex + " " + rightIndex);
			int sum = calcPoints(leftIndex, rightIndex, points);
			bw.write(sum + "\n");
		}
		bw.flush();
		br.close();
	}

	private static int calcPoints(int leftIndex, int rightIndex, int length) {
		if (rightIndex < 0 && leftIndex < 0) {
			return 0;
		}

		if (rightIndex >= length && leftIndex >= length) {
			return 0;
		}

		if (leftIndex < 0 && rightIndex >= length) {
			return length;
		}

		if (leftIndex < 0) {
			return rightIndex + 1;
		}

		if (rightIndex >= length) {
			return length - leftIndex;
		}

		return rightIndex - leftIndex + 1;
	}

	private static int getLeftIndex(int target, int length, int[] point) {
		int start = 0;
		int end = length;
		int answer = end;

		if (target < point[0]) {
			return -1;
		}
		if (point[end] < target) {
			return end + 1;
		}

		while (start <= end) {
			int mid = (start + end) / 2;

			if (target < point[mid]) {
				answer = Math.min(answer, mid);
				end = mid - 1;
			} else if (target == point[mid]) {
				return mid;
			} else {
				start = mid + 1;
			}
		}
		return answer;
	}

	private static int getRightIndex(int target, int length, int[] point) {
		int start = 0;
		int end = length;
		int answer = 0;

		if (target < point[0]) {
			return -1;
		}
		if (point[end] < target) {
			return end + 1;
		}

		while (start <= end) {
			int mid = (start + end) / 2;

			if (point[mid] < target) {
				answer = Math.max(answer, mid);
				start = mid + 1;
			} else if (point[mid] == target) {
				return mid;
			} else {
				end = mid - 1;
			}
		}

		return answer;
	}
}

이렇게 귀찮아질 바에는 반대로 생각하면 조금 더 쉬워진다. 지금은 포함되는 점의 시작점, 끝점을 구했지만

포함되지 않는 부분의 점들을 구하게 된다면 풀이는 조금 더 간단해 질 수 있음..

 

'알고리즘 공부 > boj' 카테고리의 다른 글

boj 20165: 인내의 도미노 장인 호석  (0) 2021.03.24
boj 20164: 홀수 홀릭 호석  (0) 2021.03.24
boj 19637: IF문 좀 대신 써줘  (0) 2021.03.17
boj 2805: 나무 자르기  (0) 2021.03.16
boj 2417: 정수 제곱근  (0) 2021.03.15

+ Recent posts