본문 바로가기

BAEKJOON/자료 구조

백준 1725번 [히스토그램](C++)-yes6686- 티스토리

728x90
SMALL

백준 문제 풀이: 1725 [히스토그램]


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

문제 설명:

히스토그램의 높이가 주어질 때, 직사각형의 최대 넓이를 구하는 문제입니다. 각 직사각형은 연속된 히스토그램의 높이와 폭으로 구성되며, 높이는 주어진 히스토그램의 최소 높이로 결정됩니다.


문제 해결 코드


#include <iostream>
#include <algorithm>
#define INF 2000000000
using namespace std;

int arr[100001];
int seg[400001];

int go(int n, int s, int e) {
    if (s == e) {
        seg[n] = s;
        return seg[n];
    }
    else {
        int mid = (s + e) / 2;
        int left = go(2 * n, s, mid);
        int right = go(2 * n + 1, mid + 1, e);
        if (arr[left] > arr[right]) {
            seg[n] = right;
        }
        else {
            seg[n] = left;
        }
        return seg[n];
    }
}

int fi(int n, int s, int e, int l, int r) {
    if (e < l || r < s) return INF;
    if (l <= s && r >= e) {
        return seg[n];
    }
    int mid = (s + e) / 2;
    int left = fi(n * 2, s, mid, l, r);
    int right = fi(n * 2 + 1, mid + 1, e, l, r);
    if (left == INF) return right;
    if (right == INF) return left;
    return arr[left] < arr[right] ? left : right;
}
int maxArea = -1;
int n;
void solve(int s, int e) {
    if (s > e) return;

    int index = fi(1, 0, n - 1, s, e);
    maxArea = max(maxArea, arr[index] * (e - s + 1));
    solve(s, index - 1);
    solve(index+1, e);
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> arr[i];
    }
    go(1, 0, n - 1);
    solve(0, n - 1);
    cout << maxArea;
}

코드 설명

  • 핵심 알고리즘: 세그먼트 트리를 활용하여 구간 내 최소값을 효율적으로 찾고, 분할 정복을 통해 최대 넓이를 계산합니다.
  • 구현 세부사항:
    • go 함수: 세그먼트 트리를 초기화하고 각 구간의 최소값 인덱스를 저장합니다.
    • fi 함수: 주어진 구간에서 최소값의 인덱스를 반환합니다.
    • solve 함수: 구간을 분할하며 최대 넓이를 계산합니다.
  • 시간 복잡도: O(n log n)
    • 세그먼트 트리 초기화: O(n)
    • 분할 정복 및 쿼리 처리: O(n log n)

결과

주어진 히스토그램에서 직사각형의 최대 넓이를 정확히 계산합니다. 세그먼트 트리를 이용하여 효율적으로 구간 내 최소값을 찾고, 분할 정복으로 문제를 해결했습니다.

다른 접근 방식이나 개선 사항이 있다면 댓글로 공유 부탁드립니다!

728x90
LIST