알고리즘/백준

[백준] 7662번 - 이중 우선순위 큐

땀두 2022. 3. 22. 07:48

 

처음에는 아래와 같이 무식하게 priorityQueue를 3개 만들어서 기본 pq는 다 poll을 해주고, 1과 -1일 경우 min과 max의 값을 poll해주었다. 이러한 방식으로 문제를 풀게되니 출력초과라는 결과가 나왔다.

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

public class p7662 {

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		PriorityQueue<Integer> pq = new PriorityQueue<Integer>();
		PriorityQueue<Integer> minPq = new PriorityQueue<Integer>();
		PriorityQueue<Integer> maxPq = new PriorityQueue<Integer>(Collections.reverseOrder());

		int a = Integer.parseInt(br.readLine());

		for (int i = 0; i < a; i++) {
			int n = Integer.parseInt(br.readLine());
			for (int j = 0; j < n; j++) {
				StringTokenizer st = new StringTokenizer(br.readLine());

				String idx = st.nextToken();
				int num = Integer.parseInt(st.nextToken());

				if (idx.equals("I")) {
					pq.add(num);
					maxPq.add(num);
					minPq.add(num);
				} else {
					if (pq.isEmpty()) {
						continue;
					}
					if (num == 1) {
						pq.poll();
						maxPq.poll();
					} else {
						pq.poll();
						minPq.poll();
					}
				}
			}

			if (pq.isEmpty()) {
				System.out.println("EMPTY");
			} else {
				System.out.println(maxPq.poll() + " " + minPq.poll());
			}
		}
		System.out.println(pq);
	}
}
 

그래서 비슷한 방식으로 내장함수인 remove를 이용하여 기존 pq 대신 min/max pq의 값을 지워주는 방식으로 코드를 작성하였을 때는 시간초과가 나왔다.

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

public class p7662 {

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		PriorityQueue<Integer> minPq = new PriorityQueue<Integer>();
		PriorityQueue<Integer> maxPq = new PriorityQueue<Integer>(Collections.reverseOrder());

		int a = Integer.parseInt(br.readLine());

		for (int i = 0; i < a; i++) {
			int n = Integer.parseInt(br.readLine());
			for (int j = 0; j < n; j++) {
				StringTokenizer st = new StringTokenizer(br.readLine());

				String idx = st.nextToken();
				int num = Integer.parseInt(st.nextToken());

				if (idx.equals("I")) {
					maxPq.add(num);
					minPq.add(num);
				} else {
					if (maxPq.isEmpty()) {
						continue;
					}
					if (num == 1) {
						int k = maxPq.poll();
						minPq.remove(k);
					} else {
						int k = minPq.poll();
						maxPq.remove(k);
					}
				}
			}

			if (maxPq.isEmpty()) {
				System.out.println("EMPTY");
			} else {
				System.out.println(maxPq.poll() + " " + minPq.poll());
			}
		}
	}
}
 

 

그래서 다른 풀이들을 참고하다가 TreeMap이라는 자료형을 알게되었고, 이 방식으로 문제를 풀었다.

트리맵은 레드블랙트리 기반이므로 시간복잡도가 O(logN)이기 때문에 시간제한에 걸리지 않고 문제를 풀 수 있었다.

TreeMap이라는 자료형을 처음 써봐서 사용법이 잘 익진 않았지만, firstKey와 lastKey 값을 직접 꺼낼 수 있었고, 같은 값이 다시 입력으로 들어오면 해당 key의 value를 1 증가시켜주고, 같은 값이 여러 개인 경우 1을 감소시키는 식으로 문제를 해결하였다. treeMap 내장 함수인 getOrDefault를 이용해 값이 없는 경우는 0을 넣어 null값이 되지 않게 해주는 점도 주의해주어야 한다.

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

public class p7662 {

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		int a = Integer.parseInt(br.readLine());

		for (int i = 0; i < a; i++) {
			TreeMap<Integer, Integer> map = new TreeMap<>();
			int n = Integer.parseInt(br.readLine());
			for (int j = 0; j < n; j++) {
				StringTokenizer st = new StringTokenizer(br.readLine());

				String idx = st.nextToken();
				int num = Integer.parseInt(st.nextToken());

				if (idx.equals("I")) {
					map.put(num, map.getOrDefault(num, 0) + 1);
				} else {
					if (map.isEmpty()) {
						continue;
					}
					if (num == 1) {
						if (map.get(map.lastKey()) == 1) {
							map.remove(map.lastKey());
						} else {
							map.put(map.lastKey(), map.get(map.lastKey()) - 1);
						}
					} else {
						if (map.get(map.firstKey()) == 1) {
							map.remove(map.firstKey());
						} else {
							map.put(map.firstKey(), map.get(map.firstKey()) - 1);
						}
					}
				}
			}

			if (map.isEmpty()) {
				System.out.println("EMPTY");
			} else {
				System.out.println(map.lastKey() + " " + map.firstKey());
			}
		}
	}
}