[Java] 백준 19637 IF문 좀 대신 써줘

hyunnzl·2025년 1월 2일

백준

목록 보기
30/116
post-thumbnail

https://www.acmicpc.net/problem/19637

난이도

실버3

문제

게임 개발자인 밀리는 전투력 시스템을 만들어, 캐릭터가 가진 전투력을 기준으로 칭호를 붙여주려고 한다.

예를 들어, 전투력 10,000 이하의 캐릭터는 WEAK, 10,000 초과 그리고 100,000 이하의 캐릭터는 NORMAL, 100,000 초과 그리고 1,000,000 이하의 캐릭터는 STRONG 칭호를 붙여준다고 하자. 이를 IF문으로 작성한다면 아래와 같이 구현할 수 있다.

if power <= 10000
 print WEAK
else if power <= 100000
 print NORMAL
else if power <= 1000000
 print STRONG

혼자서 게임을 개발하느라 매우 바쁜 밀리를 대신해서, 캐릭터의 전투력에 맞는 칭호를 출력하는 프로그램을 작성하자.

입력

첫 번째 줄에는 칭호의 개수 N (1 ≤ N ≤ 105)과 칭호를 출력해야 하는 캐릭터들의 개수 M (1 ≤ M ≤ 105)이 빈칸을 사이에 두고 주어진다. (1 ≤ N, M ≤ 105)

두 번째 줄부터 N개의 줄에 각 칭호의 이름을 나타내는 길이 1 이상, 11 이하의 영어 대문자로만 구성된 문자열과 해당 칭호의 전투력 상한값을 나타내는 109 이하의 음이 아닌 정수가 주어진다. 칭호는 전투력 상한값의 비내림차순으로 주어진다.

N + 2번째 줄부터 M개의 각 줄에는 캐릭터의 전투력을 나타내는 음이 아닌 정수가 주어진다. 해당하는 칭호가 없는 전투력은 입력으로 주어지지 않는다.

출력

M개의 줄에 걸쳐 캐릭터의 전투력에 맞는 칭호를 입력 순서대로 출력한다. 어떤 캐릭터의 전투력으로 출력할 수 있는 칭호가 여러 개인 경우 가장 먼저 입력된 칭호 하나만 출력한다.

내 코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

class Main {

	public static class Level implements Comparable<Level> {
		int idx, value;
		String name;

		public Level(int idx, String name, int value) {
			this.idx = idx;
			this.name = name;
			this.value = value;
		}

		@Override
		public int compareTo(Level o) {
			if (this.value != o.value) {
				return Integer.compare(this.value, o.value);
			}
			return Integer.compare(this.idx, o.idx);
		}
	}

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

		PriorityQueue<Level> pq = new PriorityQueue<>();
		for (int i = 0; i < N; i++) {
			st = new StringTokenizer(br.readLine());
			String name = st.nextToken();
			int value = Integer.parseInt(st.nextToken());
			pq.add(new Level(i, name, value));
		}

		Level[] level = new Level[N];
		for (int i = 0; i < N; i++) {
			level[i] = pq.poll();
		}

		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < M; i++) {
			int c = Integer.parseInt(br.readLine());
			
			int left = 0, right = N - 1;
			while(left < right) {
				int mid = (left + right)/2;
				right = c <= level[mid].value ? mid : right;
				left = c > level[mid].value ? mid + 1 : left;
			}
			sb.append(level[left].name).append("\n");
		}
		System.out.println(sb);
	}
}

단순 구현 문제인줄 알고 후다닥 풀고 끝내려했다가 시간초과 보고 어이가 없었다.

일단 이름이랑 레벨을 구분지을 숫자를 같이 저장해야하고, 먼저 나온 순으로 판별하는 경우도 있기 때문에 Level이라는 클래스를 선언했다.

PriorityQueue에 저장하기 위해서 정렬 조건도 클래스 내부에서 정해줬다.
1순위는 값의 크기, 만약 같다면 인덱스(문제에서 주어진 순서) 이다.

그리고 이분 탐색으로 left0, rightN-1로 시작했다.
mid를 기준으로 값이 크다면 leftmid+1로 범위를 줄여주고,
반대라면 rightmid로 내려 범위를 줄여가며 레벨을 찾아주면 된다.


0개의 댓글