https://www.acmicpc.net/problem/1933
1933호: 스카이라인
건물 수 N(1 ≤ N ≤ 100,000)은 첫 번째 줄에 표시됩니다. 다음 N 줄은 N 건물에 대한 정보를 제공합니다. 건물에 대한 정보는 건물 왼쪽의 x좌표, 건물의 높이,
www.acmicpc.net
N개의 직사각형 건물의 스카이라인을 계산하는 프로그램을 작성하세요. 스카이라인은 건물 전체의 윤곽선을 의미합니다. 즉, 각 건물을 직사각형으로 표현한다면 그 직사각형들의 합집합을 찾는 것이 문제이다.
예를 들어 직사각형 건물 세트가 있다고 가정합니다. 각 건물은 왼쪽 x 좌표, 오른쪽 x 좌표 및 고도로 표시됩니다. 단순화를 위해 모든 건물이 지상에서 동일한 높이에 있다고 가정합니다. 위의 예에서 다음과 같이 스카이라인을 얻습니다.
암호
import java.io.*;
import java.util.*;
public class Main {
public static void main(String() args) throws IOException {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
int n = Integer.parseInt(br.readLine());
List<Building> buildings = new ArrayList<>();
for (int i = 0; i < n; i++) {
st = new StringTokenizer(br.readLine());
int l = Integer.parseInt(st.nextToken());
int h = Integer.parseInt(st.nextToken());
int r = Integer.parseInt(st.nextToken());
buildings.add(new Building(l, h));
buildings.add(new Building(r, -h));
}
buildings.sort(new Comparator<Building>() {
@Override
public int compare(Building o1, Building o2) {
if (o1.x == o2.x) {
return o2.h - o1.h;
}
return o1.x - o2.x;
}
});
TreeMap<Integer, Integer> tree = new TreeMap<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
List<Building> answer = new ArrayList<>();
for (int i = 0; i < buildings.size(); i++) {
Building building = buildings.get(i);
if(building.h > 0) {
tree.put(building.h, tree.getOrDefault(building.h, 0) + 1);
} else {
int key = -building.h;
int val = tree.get(key);
if (val == 1) {
tree.remove(-building.h);
} else {
tree.put(key, val - 1);
}
}
if (tree.size() == 0) {
answer.add(new Building(building.x, 0));
continue;
}
answer.add(new Building(building.x, tree.firstKey()));
}
bw.write(answer.get(0).x + " " + answer.get(0).h + " ");
int previous = answer.get(0).h;
for (int i = 0; i < answer.size(); i++) {
if (previous != answer.get(i).h) {
bw.write(answer.get(i).x + " " + answer.get(i).h + " ");
previous = answer.get(i).h;
}
}
bw.flush();
}
private static class Building {
int x;
int h;
public Building(int x, int h) {
this.x = x;
this.h = h;
}
}
}
설명
겹치는 건물의 높이는 이전 가장 높은 건물의 높이를 따릅니다. 높이를 기준으로 정렬하는 데이터 구조를 사용해야 합니다. 겹치는 건물 중 마지막 건물을 계산하지 않기 위해 각 건물의 시작점과 끝점을 구분하여 저장한다. (+와 -로 구분) 시작점의 경우 데이터 구조에 삽입하여 갱신한다. 끝점은 시작점의 표고를 제거합니다. 계속해서 찾아 저장하고 최종적으로 정답을 출력하는 데이터 구조(답)에 가장 높은 높이를 집어넣습니다.
