[백준] 1725: 히스토그램 - JAVA
https://www.acmicpc.net/problem/1725
풀이
각 칸들의 높이가 주어지고, 내부에 가장 큰 직사각형을 구하는 문제이다.
아랫변을 구간으로 나눠 그 구간으로 이룰 수 있는 직사각형의 넓이를 비교해주었다.
세그먼트트리에는 구간별로 최소 높이를 갖는 인덱스를 저장해주었다.
구간으로 탐색할 때 인덱스를 기준으로 나누기 위함이다.
(1, N)구간에서 넓이를 구하면 밑변은 (N - 1 + 1)이 되고, 높이는 해당 구간의 최소 높이를 세그먼트트리에서 찾아주면 된다. 이렇게 구한것이 해당 구간에서 만들수있는 직사각형의 최대이다.
위에서 찾은 최소 높이의 인덱스를 idx라고 하면 (1, idx - 1), (idx + 1, N)으로 나누어 계속 진행한다.
메모리: 39272KB
시간: 356ms
언어: Java 11
코드
import java.io.*;
import java.util.*;
public class Main {
static class SegmentTree {
int[] tree;
public SegmentTree(int arrSize) {
tree = new int[arrSize * 4];
}
public int init(int node, int start, int end) {
if (start == end) {
return tree[node] = start;
} else {
int a = init(node * 2, start, (start + end) / 2);
int b = init(node * 2 + 1, (start + end) / 2 + 1, end);
return tree[node] = arr[a] < arr[b] ? a : b;
}
}
public int find(int node, int start, int end, int left, int right) {
if (left > end || right < start) {
return 0;
}
if (left <= start && end <= right) {
return tree[node];
}
int a = find(node * 2, start, (start + end) / 2, left, right);
int b = find(node * 2 + 1, (start + end) / 2 + 1, end, left, right);
return arr[a] < arr[b] ? a : b;
}
}
static int N;
static long[] arr;
static SegmentTree seg;
static long ans;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());
arr = new long[N + 1];
for (int i = 1; i < N + 1; i++) {
arr[i] = Integer.parseInt(br.readLine());
}
arr[0] = Long.MAX_VALUE;
seg = new SegmentTree(N);
seg.init(1, 1, N);
ans = 0;
solve(1, N);
System.out.println(ans);
}
private static void solve(int left, int right) {
if (left > right) {
return;
}
int idx = seg.find(1, 1, N, left, right);
ans = Math.max(ans, arr[idx] * (right - left + 1));
solve(left, idx - 1);
solve(idx + 1, right);
}
}