사용한 것
- 히스토그램에서 가장 큰 직사각형을 효율적으로 구하기 위한 Stack
풀이 방법
heights
의 마지막 인덱스에 -1을 넣고 stack
에 -1을 push()
한다.
- 사용할 전략이 현재 인덱스 높이가 더 작은 경우
stack
에 쌓은 값들로 직사각형의 넓이를 구하므로 heights
의 마지막 인덱스에 -1을 넣는 것이다.
stack
에 -1을 push()
하는 이유는 기본적인 left
를 정의해준 것이다.
- 현재 인덱스(
right
)를 증가시키며
- 현재 인덱스가
stack
의 top보다 같거나 큰 값이 들어오면 push()
만 수행한다.
- 현재 인덱스가
stack
의 top보다 작은 경우 현재 인덱스의 높이보다 stack
원소의 높이가 더 클때까지 직사각형 넓이를 계산한다.
stack
에는 오름차순으로 정렬되어있기 때문에 pop()
한 mid
의 높이가 left
의 것보다 크고 right - 1
의 높이보다 작다.
- 따라서
mid
의 높이를 가지는 직사각형은 heights[mid] * (right - left - 1)
이다.
코드
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
StringBuilder sb = new StringBuilder();
int n, mid, left;
int[] heights;
long answer;
Stack<Integer> stack;
while (true) {
st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
if (n == 0) {
break;
}
heights = new int[n + 1];
for (int i = 0; i < n; i++) {
heights[i] = Integer.parseInt(st.nextToken());
}
answer = 0;
heights[n] = -1;
stack = new Stack<>();
stack.push(-1);
for (int right = 0; right < heights.length; right++) {
while (stack.size() > 1 && heights[right] < heights[stack.peek()]) {
mid = stack.pop();
left = stack.peek();
answer = Math.max((long) heights[mid] * (right - left - 1), answer);
}
stack.push(right);
}
sb.append(answer).append(lineSeparator());
}
System.out.println(sb);
}
}