Post

BOJ 2457 공주님의 정원

BOJ 2457 공주님의 정원

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

문제

오늘은 공주님이 태어난 경사스러운 날이다. 왕은 이 날을 기념하기 위해 늘 꽃이 피어있는 작은 정원을 만들기로 결정했다.

총 N개의 꽃이 있는 데, 꽃은 모두 같은 해에 피어서 같은 해에 진다. 하나의 꽃은 피는 날과 지는 날이 정해져 있다. 예를 들어, 5월 8일 피어서 6월 13일 지는 꽃은 5월 8일부터 6월 12일까지는 꽃이 피어 있고, 6월 13일을 포함하여 이후로는 꽃을 볼 수 없다는 의미이다. (올해는 4, 6, 9, 11월은 30일까지 있고, 1, 3, 5, 7, 8, 10, 12월은 31일까지 있으며, 2월은 28일까지만 있다.)

이러한 N개의 꽃들 중에서 다음의 두 조건을 만족하는 꽃들을 선택하고 싶다.

공주가 가장 좋아하는 계절인 3월 1일부터 11월 30일까지 매일 꽃이 한 가지 이상 피어 있도록 한다. 정원이 넓지 않으므로 정원에 심는 꽃들의 수를 가능한 적게 한다. N개의 꽃들 중에서 위의 두 조건을 만족하는, 즉 3월 1일부터 11월 30일까지 매일 꽃이 한 가지 이상 피어 있도록 꽃들을 선택할 때, 선택한 꽃들의 최소 개수를 출력하는 프로그램을 작성하시오.


입력

첫째 줄에는 꽃들의 총 개수 N (1 ≤ N ≤ 100,000)이 주어진다. 다음 N개의 줄에는 각 꽃이 피는 날짜와 지는 날짜가 주어진다. 하나의 날짜는 월과 일을 나타내는 두 숫자로 표현된다. 예를 들어서, 3 8 7 31은 꽃이 3월 8일에 피어서 7월 31일에 진다는 것을 나타낸다.


출력

첫째 줄에 선택한 꽃들의 최소 개수를 출력한다. 만약 두 조건을 만족하는 꽃들을 선택할 수 없다면 0을 출력한다.


예제 입력 1

4
1 1 5 31
1 1 6 30
5 15 8 31
6 10 12 10

예제 출력 1

2

예제 입력 2

10
2 15 3 23
4 12 6 5
5 2 5 31
9 14 12 24
6 15 9 3
6 3 6 15
2 28 4 25
6 15 9 27
10 5 12 31
7 14 9 1

예제 출력 2

5

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

public class Main {
    static class Flower implements Comparable<Flower>{
        int start, end;

        // 월, 일을 MMDD와 같은 형태로 저장하기 위한 초기화
        public Flower(int sMonth, int sDay, int eMonth, int eDay) {
            this.start = sMonth * 100 + sDay;
            this.end = eMonth * 100 + eDay;
        }

        @Override
        public int compareTo(Flower o) {
            return start - o.start;
        }
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        // 꽃이 피는 날짜가 가장 빠른 것부터 꺼내기 위한 우선순위 큐
        PriorityQueue<Flower> queue = new PriorityQueue<>();
        int N = Integer.parseInt(br.readLine());
        for (int i = 0; i < N; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            queue.offer(new Flower(
                    Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()),
                    Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken())
            ));
        }
        // 가장 빨리 피는 꽃이 3월 1일 이후에 필 경우, 조건을 충족시키지 못하므로 0 출력
        if(queue.peek().start > 3_01) {
            System.out.println(0);
            return;
        }

        /**
         * 1. 꽃이 피는 날짜가 3월 1일까지인 꽃들 중에서 가장 길게 피어있는 꽃을 찾은 후
         * 2. 해당 꽃이 지는 날짜를 latest에 저장함
         * 3. 1번으로 돌아가 꽃이 피는 날짜가 latest 이전인 꽃들 중에서 가장 길게 피어있는 꽃을 찾음
         * 4. 위 과정을 latest가 12월 1일 이후가 될 때까지 반복
         */
        int answer = 0, latest = 3_01;
        while (!queue.isEmpty() && latest < 12_01) {
            // 꽃이 피는 날짜가 latest 이전인 꽃들 중 가장 길게 피어있는 꽃을 저장하기 위한 변수 max
            Flower max = queue.poll();
            // 예를 들어, 5월 1일 이후에 가장 빨리 피는 꽃이 6월 1일인 경우와 같이
            // 중간에 꽃이 피지 않는 기간이 있을 경우를 찾기 위한 조건문
            if(max.start > latest) break;
            // 꽃이 피는 날짜가 latest 이전인 꽃들 중에서 가장 길게 피어있는 꽃을 찾기 위한 반복문
            while (!queue.isEmpty() && queue.peek().start <= latest) {
                Flower check = queue.poll();
                if(check.end > max.end) {
                    max = check;
                }
            }
            // 위 과정을 거쳐 찾은 가장 길게 피어있는 꽃의 피는 날짜를 latest에 저장 후 answer++
            latest = max.end;
            answer++;
        }

        // 위 과정을 거쳐 찾은 가장 길게 피어있는 꽃이 지는 날짜가 12월 이전일 경우, 조건을 만족하지 못하므로 0 출력
        System.out.println(latest >= 12_01 ? answer : 0);
    }
}
This post is licensed under CC BY 4.0 by the author.