둠치킨
코딩하는 둠치킨
둠치킨

블로그 메뉴

  • 홈
  • 분류 전체보기 (220) N
    • BOJ (173) N
      • 스택 (14)
      • 큐 (5)
      • 덱 (4)
      • 그래프 (30)
      • 배열 (8)
      • 재귀 (12)
      • 브루트 포스 (2)
      • 그리디 알고리즘 (7)
      • 다이내믹 프로그래밍 (13)
      • 백트래킹 (24)
      • 기하학 (4)
      • 트리 (4)
      • 구현 (14)
      • 수학 (3)
      • 맵 (1)
      • 다익스트라 (2)
      • 누적합 (5)
      • 유니온 파인드 (2) N
    • 자료구조 (14)
      • 스택 (3)
      • 큐 (5)
      • 덱 (2)
      • 그래프 (1)
      • 트리 (1)
      • 힙 (1)
      • 정렬 (1)
    • C++ (11)
      • 모두의코드 (2)
      • Effective C++ (3)
      • C++ STL (6)
    • 컴파일러 (1)
    • OS (17)
    • 컴퓨터 구조 (2)
    • Unreal Engine 5 (2)

공지사항

전체 방문자
오늘
어제

인기 글

최근 글

태그

  • BFS
  • boj
  • Bruteforce
  • C
  • C++
  • C++ STL
  • Cache Memory
  • deadlock
  • DFS
  • Effective C++
  • java
  • Mutex
  • next_permutation
  • os
  • Process
  • rotate
  • semaphore
  • spin lock
  • STL
  • STL C++
hELLO · Designed By 정상우.
둠치킨

코딩하는 둠치킨

6549번: 히스토그램에서 가장 큰 직사각형 (BOJ C/C++)
BOJ/트리

6549번: 히스토그램에서 가장 큰 직사각형 (BOJ C/C++)

2022. 2. 24. 23:39

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

사용 언어: C++

문제

히스토그램은 직사각형 여러 개가 아래쪽으로 정렬되어 있는 도형이다. 각 직사각형은 같은 너비를 가지고 있지만, 높이는 서로 다를 수도 있다. 예를 들어, 왼쪽 그림은 높이가 2, 1, 4, 5, 1, 3, 3이고 너비가 1인 직사각형으로 이루어진 히스토그램이다.

히스토그램에서 가장 넓이가 큰 직사각형을 구하는 프로그램을 작성하시오.

입력

입력은 테스트 케이스 여러 개로 이루어져 있다. 각 테스트 케이스는 한 줄로 이루어져 있고, 직사각형의 수 n이 가장 처음으로 주어진다. (1 ≤ n ≤ 100,000) 그다음 n개의 정수 h1, ..., hn (0 ≤ hi ≤ 1,000,000,000)가 주어진다. 이 숫자들은 히스토그램에 있는 직사각형의 높이이며, 왼쪽부터 오른쪽까지 순서대로 주어진다. 모든 직사각형의 너비는 1이고, 입력의 마지막 줄에는 0이 하나 주어진다.

출력

각 테스트 케이스에 대해서, 히스토그램에서 가장 넓이가 큰 직사각형의 넓이를 출력한다.

 

풀이

코드를 그림을 보면서 이해하고 싶으면 https://sexycoder.tistory.com/107을 한번 보는 것을 추천한다.

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

//세그먼트 트리를 초기화할 때 해당 구간 내 가장 낮은 막대의 인덱스를 저장

void init(vector<long long> &array, vector<long long> &tree, int node, int start, int end)
{
    // start 와 end 의 위치가 일치하면 start 값을 넣어준다
	if(start == end)
		tree[node] = start;
    else
	{
		int mid = (start + end) / 2;
		init(array, tree, node * 2, start, mid);
		init(array, tree, node * 2 + 1, mid + 1, end);

		//각 구간에서 가장 높이가 낮은 것을 노드에 넣어준다
		
		array[tree[node * 2]] < array[tree[node * 2 + 1]]
			? tree[node] = tree[node * 2] : tree[node] = tree[node * 2 + 1];
	}
}

//구간에서 가장 최소인 높이의 막대 인덱스 구하기

int query(vector<long long> &array, vector<long long> &tree, int node, int start, int end, int i, int j)
{
	// 찾아야하는 구간과 노드구간이 겹치지 않을 때
	if(end<i || start>j)
		return -1;
	// 찾아야하는 구간내에 노드구간이 포함될 때
	else if(i <= start && end <= j)
		return tree[node];
	
	int mid = (start + end) / 2;
	int leftQuery = query(array, tree, node * 2, start, mid, i, j);
	int rightQuery = query(array, tree, node * 2 + 1, mid + 1, end, i, j);

	// 찾는 구간이 노드구간에 포함되거나, 부분적으로 겹치는 경우
	if(leftQuery == -1)
		return rightQuery;
	
	else if(rightQuery == -1)
		return leftQuery;
	
	else return array[leftQuery] < array[rightQuery] ? leftQuery : rightQuery;
}

long long getMaxArea(vector<long long> &array, vector<long long> &tree, int start, int end)
{
	int N = array.size() - 1;
	int idx = query(array, tree, 1, 1, N, start, end); 
	long long area = (end - start + 1) * array[idx];

	//왼쪽 막대 존재하면 왼쪽 최대 넓이 구하기
	if(start < idx)
	{
		long long temp = getMaxArea(array, tree, start, idx - 1);
		area = max(area, temp);
	}
	
	//오른쪽 막대 존재하면 오른쪽 최대 넓이 구하기
	if(idx < end)
	{
		long long temp = getMaxArea(array, tree, idx + 1, end);
		area = max(area, temp);
	}
	
	return area;
}

int main(void)
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	
	while(1)
	{
		int N;
		cin >> N;
		if (N == 0)
			 break;
		vector<long long> arr(N + 1);
		for (int i = 1; i <= N; i++)
			 cin >> arr[i];

		//세그먼트 트리 크기
		int Tree_Height = (int)ceil(log2(N));
		int Tree_Size = (1 << (Tree_Height + 1));
		vector<long long> tree(Tree_Size);
		init(arr, tree, 1, 1, N);
		cout << getMaxArea(arr, tree, 1, N) << "\n";
	}
	return 0;
}
저작자표시 (새창열림)

'BOJ > 트리' 카테고리의 다른 글

11279번: 최대 힙 (BOJ C/C++)  (0) 2022.02.18
1927번: 최소 힙 (BOJ C/C++)  (0) 2022.02.18
1991번: 트리 순회 (BOJ C/C++)  (0) 2022.02.05
    'BOJ/트리' 카테고리의 다른 글
    • 11279번: 최대 힙 (BOJ C/C++)
    • 1927번: 최소 힙 (BOJ C/C++)
    • 1991번: 트리 순회 (BOJ C/C++)
    둠치킨
    둠치킨
    코딩 공부를 위한 코딩 블로그 기록 일기

    티스토리툴바