어흥

[백준 6549] 히스토그램에서 가장 큰 직사각형 (C++) 본문

알고리즘/백준

[백준 6549] 히스토그램에서 가장 큰 직사각형 (C++)

라이언납시오 2021. 5. 18. 18:53
728x90
반응형

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

 

6549번: 히스토그램에서 가장 큰 직사각형

입력은 테스트 케이스 여러 개로 이루어져 있다. 각 테스트 케이스는 한 줄로 이루어져 있고, 직사각형의 수 n이 가장 처음으로 주어진다. (1 ≤ n ≤ 100,000) 그 다음 n개의 정수 h1, ..., hn (0 ≤ hi ≤

www.acmicpc.net

1. 주의할 점

- 분할정복 + 세그먼트 트리를 통해 해결한다

 

2. 구현

- 직사각형의 높이에 대한 정보를 Arr[] 배열에 담는다

- Tree[] 배열을 동적할당한다

- Init() 배열을 통해 Tree[] 배열에 최소 높이를 가지는 인덱스 번호를 저장한다

- findMinIdx() 함수를 통해 Left~Right까지의 Arr[] 배열에서 가장 낮은 높이를 갖는 인덱스를 반환한다. 이때, 범위가 Start와 End의 사이가 아니라면 -1을 반환한다

- findMaxArea() 함수 내부에서는 findMinIdx() 함수를 통해 Left~Right사이에 위치한 가장 작은 높이를 가진 인덱스를 구한다. 이때, Temp에는 Arr[minIdx]*너비를 통해 현재 만들 수 있는 가장 큰 직사각형을 구하고 Result와 비교한다

- minIdx가 Left보다 오른쪽에 위치한다면, [Left,minIdx) 사이의 findMaxArea()를 수행한다

- minIdx가 Right보다 왼쪽에 위치한다면, (minIdx,Right] 사이의 findMaxArea()를 수행한다

#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
int *tree;
long long arr[100000];
long long result,curH;
int num;

int init(int node, int start, int end){
    if(start==end) return tree[node] = start;
    int mid = start + (end-start)/2;
    int lidx = init(2*node,start,mid);
    int ridx = init(2*node+1,mid+1,end);
    return tree[node] = arr[lidx] > arr[ridx] ? ridx : lidx;
}

int findMinIdx(int node, int start, int end, int left, int right){
    if(left>end || right<start) return -1;
    if(left<=start && end<=right) return tree[node];
    int mid = start + (end-start)/2;
    int lidx = findMinIdx(node*2, start, mid, left, right);
    int ridx = findMinIdx(node*2+1, mid+1, end, left, right);
    
    if(lidx==-1) return ridx;
    else if(ridx==-1) return lidx;
    return arr[lidx] > arr[ridx] ? ridx: lidx;
}

void findMaxArea(int left, int right){
    int minIdx = findMinIdx(1,0,num-1,left,right);
    long long temp = arr[minIdx]*(right-left+1);
    result = max(result,temp);
    if(left<minIdx)
        findMaxArea(left,minIdx-1);
    if(minIdx<right)
        findMaxArea(minIdx+1,right);
}

int main() {
    ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    int height;
    while(1){
        cin>>num;
        if(num==0) break;
        height = ceil(log2(num));
        tree = new int[1<<(height+1)];
        //초기화
        for(int i=0;i<num;i++)
            cin>>arr[i];
        init(1,0,num-1);
        result=0;
        findMaxArea(0,num-1);
        cout<<result<<'\n';
    }
    return 0;
}
728x90
반응형

'알고리즘 > 백준' 카테고리의 다른 글

[백준 3653] 영화 수집 (C++)  (0) 2021.06.02
[백준 7578] 공장 (C++)  (0) 2021.06.01
[백준 11505] 구간 곱 구하기 (C++)  (0) 2021.05.17
[백준 2357] 최솟값과 최댓값 (C++)  (0) 2021.05.13
[백준 1275] 커피숍2 (C++)  (0) 2021.05.13
Comments