[c++] 세그먼트 트리(Segment Tree) 데이터 구조

세그먼트 트리는 배열이나 리스트와 같은 자료 구조에서 구간 쿼리를 빠르게 처리할 수 있도록 도와주는 자료 구조입니다. 세그먼트 트리는 공간 복잡도 O(n)과 시간 복잡도 O(log n)을 가지며, 주로 구간 합, 최댓값, 최솟값 등을 빠르게 계산할 때 사용됩니다.

구현

#include <vector>

using namespace std;

class SegmentTree {
private:
    vector<int> tree;
    int n;

public:
    SegmentTree(vector<int>& nums) {
        n = nums.size();
        tree.resize(4 * n);
        build(nums, 1, 0, n - 1);
    }

    void build(vector<int>& nums, int node, int start, int end) {
        if (start == end) {
            tree[node] = nums[start];
            return;
        }

        int mid = (start + end) / 2;
        build(nums, node * 2, start, mid);
        build(nums, node * 2 + 1, mid + 1, end);
        tree[node] = tree[node * 2] + tree[node * 2 + 1];
    }

    void update(int index, int val) {
        update(1, 0, n - 1, index, val);
    }

    void update(int node, int start, int end, int index, int val) {
        if (start == end) {
            tree[node] = val;
            return;
        }

        int mid = (start + end) / 2;
        if (index <= mid) {
            update(node * 2, start, mid, index, val);
        } else {
            update(node * 2 + 1, mid + 1, end, index, val);
        }
        tree[node] = tree[node * 2] + tree[node * 2 + 1];
    }

    int query(int left, int right) {
        return query(1, 0, n - 1, left, right);
    }

    int query(int node, int start, int end, int left, int right) {
        if (right < start || end < left) {
            return 0;
        }

        if (left <= start && end <= right) {
            return tree[node];
        }

        int mid = (start + end) / 2;
        return query(node * 2, start, mid, left, right) + query(node * 2 + 1, mid + 1, end, left, right);
    }
};

사용 예제

#include <iostream>
#include <vector>

using namespace std;

int main() {
    vector<int> nums = {1, 3, 5, 7, 9, 11};
    SegmentTree st(nums);

    cout << st.query(1, 3) << endl;  // 15
    st.update(1, 6);
    cout << st.query(1, 3) << endl;  // 18

    return 0;
}

세그먼트 트리는 구간 쿼리를 빠르게 처리할 수 있으며, 위의 예제에서 보듯이 빠른 시간 내에 구간의 합을 구할 수 있습니다.

더 많은 정보를 알고 싶으시다면, 아래의 참고 자료를 참고하시기 바랍니다.

참고 자료