문제 설명

문제 링크

http://icpc.me/9345

 

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

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

www.acmicpc.net

풀이

세그먼트 트리를 이용하여 풀이할 수 있다.

a ~ b 사이에 a, a+1, ... , b 만 존재한다면 이때 최솟값은 a 최댓값은 b이다. 만약 저 구간에 다른 값이 들어간다면 최솟값, 최댓값은 a, b가 될 수 없다.

이 구간 최대, 최소값을 세그먼트 트리로 관리하면 쿼리당 O(logN)에 처리할 수 있다. 

코드

#include <cstdio>
#include <algorithm>

using namespace std;
using pii = pair<int, int>;

pii tree[400005];
int loc[100005];

pii init(int node, int s, int e) {
    if (s == e) return tree[node] = {s, s};
    int mid = (s + e) >> 1;
    pii left = init(2 * node, s, mid);
    pii right = init(2 * node + 1, mid + 1, e);
    return tree[node] = {min(left.first, right.first), max(left.second, right.second)};
}

pii query(int node, int s, int e, int qs, int qe) {
    if (e < qs || qe < s) return {1e9, -1e9};
    if (qs <= s && e <= qe) return tree[node];
    int mid = (s + e) >> 1;
    pii left = query(2 * node, s, mid, qs, qe);
    pii right = query(2 * node + 1, mid + 1, e, qs, qe);
    return {min(left.first, right.first), max(left.second, right.second)};
}

pii update(int node, int s, int e, int idx, int num) {
    if (idx < s || idx > e) return tree[node];
    if (s == e) return tree[node] = {num, num};
    int mid = (s + e) >> 1;
    pii left = update(2 * node, s, mid, idx, num);
    pii right = update(2 * node + 1, mid + 1, e, idx, num);
    return tree[node] = {min(left.first, right.first), max(left.second, right.second)};
}

void solve() {
    int n, k; scanf("%d %d", &n, &k);
    init(1, 0, n - 1);
    for (int i = 0; i < n; i++) loc[i] = i;
    while (k--) {
        int q, a, b; scanf("%d %d %d", &q, &a, &b);
        if (!q) {
            update(1, 0, n - 1, loc[a], b);
            update(1, 0, n - 1, loc[b], a);
            swap(loc[a], loc[b]);
        } else {
            auto [m, M] = query(1, 0, n - 1, a, b);
            if (a == m && b == M) printf("YES\n");
            else printf("NO\n");
        }
    }
}

int main() {
    int t; scanf("%d", &t);
    while (t--) {
        solve();
    }
}

'Algorithm > BOJ' 카테고리의 다른 글

백준[12899] 데이터 구조  (0) 2021.08.19
백준[16975] 수열과 쿼리 21  (0) 2021.08.16
백준[1517] 버블 소트  (0) 2021.08.11
백준[11660] 구간 합 구하기 5  (0) 2021.08.10
백준[16991] 외판원 순회 3  (0) 2021.08.10
복사했습니다!