ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [14428] 수열과 쿼리 16
    BOJ 2021. 8. 30. 22:00

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

     

    14428번: 수열과 쿼리 16

    길이가 N인 수열 A1, A2, ..., AN이 주어진다. 이때, 다음 쿼리를 수행하는 프로그램을 작성하시오. 1 i v : Ai를 v로 바꾼다. (1 ≤ i ≤ N, 1 ≤ v ≤ 109) 2 i j : Ai, Ai+1, ..., Aj에서 크기가 가장 작은 값의

    www.acmicpc.net

    <문제>
    최소값을 찾는 세그먼트 트리를 구현하고, 값 대신 인덱스를 리턴하도록 만들면 된다.
    리프노드에는 인덱스가, 그 외에는 구간중 최소값을 갖는 인덱스가 들어가도록 구성한 다음에,
    인덱스를 리턴하는 부분을 처리하기 위해 minIdx라는 함수를 만들었다.
    단순히 최소값을 리턴하는 문제라면, (left>end || right<start)일때 INF를 리턴하면 되지만
    이 문제는 -1같이 절대 인덱스로는 불가능한 숫자를 리턴하고, 이를 아예 판단에서 배제하는 과정이 필요했다.
    query에서 범위가 대상 밖일때에는 -1을 리턴하고, minIdx에서 한쪽이 -1인 경우는 반대쪽을
    리턴하도록 함으로써 인덱스에 대한 처리가 끝난다.

    <소스코드>

    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
    #include<stdio.h>
    #include<vector>
    #include<limits.h>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    vector <ll>num;
    vector <ll>segTree;
    int n, m;
    ll minIdx(ll x, ll y) {
        if (x == -1)return y;
        if (y == -1)return x;
        if (num[x] == num[y])return x < y ? x : y;
        return num[x] < num[y] ? x : y;
    }
    ll makeSegTree(int node, int start, int end) {
        if (start == end)return segTree[node] = start;
        int mid = (start + end/ 2;
        return segTree[node] = minIdx(makeSegTree(node * 2, start, mid), makeSegTree(node * 2 + 1, mid + 1end));
    }
    ll updateSegTree(int node, int start, int endint idx) {
        if (idx<start || idx>end)return segTree[node];
        if (start == end) {
            return segTree[node];
        }
        int mid = (start + end/ 2;
        return segTree[node] = minIdx(updateSegTree(node * 2, start, mid, idx),
            updateSegTree(node * 2 + 1, mid + 1end, idx));
    }
    ll query(int node, int start, int endint left, int right) {
        if (left > end || right < start)return -1;
        if (left <= start && end <= right)return segTree[node];
        int mid = (start + end/ 2;
        return minIdx(query(node * 2, start, mid, left, right), query(node * 2 + 1, mid + 1end, left, right));
    }
    int main(void) {
        int i;
        scanf("%d"&n);
        num.resize(n + 3);
        segTree.resize(4 * n);
        for (i = 1; i <= n; i++)
            scanf("%lld"&num[i]);
        makeSegTree(11, n);
        scanf("%d"&m);
        for (i = 0; i < m; i++) {
            int a;
            scanf("%d"&a);
            if (a == 1) {
                int idx;
                ll value;
                scanf("%d %lld"&idx, &value);
                num[idx] = value;
                updateSegTree(11, n, idx);
            }
            else if (a == 2) {
                int s, e;
                scanf("%d %d"&s, &e);
                printf("%lld\n", query(11, n, s, e));
            }
        }
        return 0;
    }
    cs
     

     

    'BOJ' 카테고리의 다른 글

    [14003] 가장 긴 증가하는 부분 수열 5  (0) 2021.08.30
    [2206] 벽 부수고 이동하기  (0) 2021.08.30
    [6549] 히스토그램에서 가장 큰 직사각형  (0) 2021.08.30
    [15685] 드래곤 커브  (0) 2021.08.30
    [10451] 순열 사이클  (0) 2021.08.30

    댓글