본문 바로가기

BAEKJOON/자료 구조

백준 10868번 [최솟값](C++)-yes6686- 티스토리

728x90
SMALL

백준 문제 풀이: 10868 [최솟값]


문제 링크: https://www.acmicpc.net/problem/10868

문제 설명:

주어진 수열에서 특정 구간의 최솟값을 빠르게 구하는 문제입니다. n개의 수가 주어지고, m개의 구간에 대한 최솟값을 각각 출력해야 합니다.


문제 해결 코드


#include <iostream>
#include <algorithm>
using namespace std;

int arr[100001];

struct Seg {
    int ma;
    int mi;
};

Seg seg[400001];

Seg go(int n, int s, int e) {
    if (s == e) {
        seg[n].ma = arr[s];
        seg[n].mi = arr[s];
        return seg[n];
    } else {
        int mid = (s + e) / 2;
        Seg left = go(2 * n, s, mid);
        Seg right = go(2 * n + 1, mid + 1, e);
        seg[n].ma = max(left.ma, right.ma);
        seg[n].mi = min(left.mi, right.mi);
        return seg[n];
    }
}

Seg ans;
Seg fi(int n, int s, int e, int l, int r) {
    if (e < l || r < s) return ans;
    if (l <= s && r >= e) {
        return seg[n];
    }
    int mid = (s + e) / 2;
    Seg left = fi(n * 2, s, mid, l, r);
    Seg right = fi(n * 2 + 1, mid + 1, e, l, r);
    ans.ma = max(left.ma, right.ma);
    ans.mi = min(left.mi, right.mi);
    return ans;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    int n, m;
    cin >> n >> m;
    for (int i = 0; i < n; i++) {
        cin >> arr[i];
    }
    go(1, 0, n - 1);
    int a, b;
    for (int i = 0; i < m; i++) {
        cin >> a >> b;
        ans.ma = 0;
        ans.mi = 1000000000;
        cout << fi(1, 0, n - 1, a - 1, b - 1).mi << '\n';
    }
}

코드 설명

  • 세그먼트 트리 초기화: 함수 go는 주어진 배열을 기반으로 세그먼트 트리를 초기화합니다.
  • 구간 최솟값 계산: 함수 fi는 특정 구간의 최솟값을 효율적으로 구합니다.
  • 시간 복잡도: 세그먼트 트리 구축은 O(n), 각 쿼리는 O(log n)입니다. 따라서 총 시간 복잡도는 O(n + m log n)입니다.

결과

세그먼트 트리를 사용하여 구간 최솟값 문제를 효율적으로 해결했습니다. 개선점이나 추가적인 질문이 있다면 댓글로 알려주세요!

728x90
LIST