ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [BOJ 9345, C++] 디지털 비디오 디스크(DVDs)
    알고리즘/BOJ 2021. 7. 29. 22:02
    반응형

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

     

    9345번: 디지털 비디오 디스크(DVDs)

    손님이 DVD를 카운터에 가져왔을 때 손님이 원하는 DVD가 전부 존재하면, (A번 선반부터 B번 선반까지에 있는 DVD를 전부 가져왔을 때 순서에 상관없이 A번 DVD부터 B번 DVD까지 있다면) "YES"를 출력하

    www.acmicpc.net

     

     

    풀이

    [L, R] 범위에 책이 모두 있는지 확인하는 방법은 첫 번째로 머지 소트 트리를 통하여 DVD가 L부터 R까지 있는지 확인해볼 수 있습니다.

    머지 소트 트리가 정렬된 DVD 번호를 가져오니까 만약 [L, R]이 입력 값으로 들어온다면 [L, L+1, L+2, ... , R-1, R]로 들어오겠네요.

     

    여기서 좀 더 생각해보면 우리가 머지 소트 트리를 사용하는 이유는 맨 왼쪽값이 L인지, 맨 오른쪽 값이 R인지 확인해보려고 만든 것입니다. 이걸 다르게 말하면 최솟값이 L인지, 최댓값이 R인지 확인만 하면 된다는 것이죠.

    만약 폐구간 [L, R] 범위안에 있는 값 K대신 폐구간에 해당하지 않는 다른 값 x가 들어간다고 가정해봅시다. 이때 x > R이라면 [L +1, L+2, .., K-1, K+1, ... , R -1, R, x]로 맨 오른쪽 값이 x가 되어 답이 아니게 됩니다. 다르게 말하면 최댓값이 R이 아니게 되는 것이죠.

     

    그래서 최솟값을 찾는 세그먼트트리, 최댓값을 찾는 세그먼트트리를 이용하여 최솟값이 L인지, 최댓값이 R인지 확인해주면 됩니다.

     

     

    코드

    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
    70
    #include <iostream>
    using namespace std;
    typedef long long ll;
     
    const int N = 1e5 + 1;
    int n, m, t;
    int arr[N], min_tree[4 * N], max_tree[4 * N];
     
     int min_update(int now, int s, int e, int idx, int val) {
        if (s > idx || e < idx) return min_tree[now];
        if (s == e) return min_tree[now] = val;
        int mid = (s + e) / 2;
        return min_tree[now] = min(min_update(now * 2, s, mid, idx, val), min_update(now * 2 + 1, mid + 1, e, idx, val));
     }
     
    int max_update(int now, int s, int e, int idx, int val) {
        if (s > idx || e < idx) return max_tree[now];
        if (s == e) return max_tree[now] = val;
        int mid = (s + e) / 2;
        return max_tree[now] = max(max_update(now * 2, s, mid, idx, val), max_update(now * 2 + 1, mid + 1, e, idx, val));
    }
     
    int find_min(int now, int s, int e, int L, int R) {
        if (R<|| L>e) return 987654321;
        if (L <= s && e <= R) return min_tree[now];
        int mid = (s + e) / 2;
        return min(find_min(now * 2, s, mid, L, R), find_min(now * 2 + 1, mid + 1, e, L, R));
    }
     
    int find_max(int now, int s, int e, int L, int R) {
        if (R<|| L>e) return 0;
        if (L <= s && e <= R) return max_tree[now];
        int mid = (s + e) / 2;
        return max(find_max(now * 2, s, mid, L, R), find_max(now * 2 + 1, mid + 1, e, L, R));
    }
     
    int main() {
        ios_base::sync_with_stdio(false);
        cin.tie(NULL);
        cin >> t;
        while (t--) {
            cin >> n >> m;
     
            for (int i = 0; i < n; i++) {
                arr[i] = i;
                min_update(10, n - 1, i, i);
                max_update(10, n - 1, i, i);
            }
     
            for (int i = 0; i < m; i++) {
                int a, b, c;
                cin >> a >> b >> c;
                if (a == 0) {
                    min_update(10, n - 1, b, arr[c]);
                    max_update(10, n - 1, b, arr[c]);
                    min_update(10, n - 1, c, arr[b]);
                    max_update(10, n - 1, c, arr[b]);
                    int x = arr[b];
                    arr[b] = arr[c];
                    arr[c] = x;
                }
                else {
                    int x = find_min(10, n - 1, b, c);
                    int y = find_max(10, n - 1, b, c);
                    if (x == b && y == c) cout << "YES" << '\n';
                    else cout << "NO" << '\n';
                }
            }
        }
    }
    cs
    반응형

    댓글

Designed by Tistory.