TIL
오늘 배운 것
boj 1186
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
// 직사각형 정보를 저장할 클래스
class Rectangle {
int id;
int x1, y1, x2, y2;
int gridX1, gridY1, gridX2, gridY2;
long area; // 넓이는 int 범위를 넘어설 수 있으므로 long 타입 사용
public Rectangle(int id, int x1, int y1, int x2, int y2) {
this.id = id;
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.area = 0;
}
// 실제 좌표를 압축된 그리드 좌표로 변환
public void setGridCoordinates(List<Integer> xCoords, List<Integer> yCoords) {
this.gridX1 = Collections.binarySearch(xCoords, this.x1);
this.gridX2 = Collections.binarySearch(xCoords, this.x2);
this.gridY1 = Collections.binarySearch(yCoords, this.y1);
this.gridY2 = Collections.binarySearch(yCoords, this.y2);
}
// 다른 상위 사각형이 차지하지 않은 영역의 넓이를 계산하고 차지함(used=true)
public void calculateAndPaintArea(boolean[][] used, long[] gridXWidths, long[] gridYHeights) {
this.area = 0;
for (int x = gridX1; x < gridX2; x++) {
for (int y = gridY1; y < gridY2; y++) {
if (!used[x][y]) {
used[x][y] = true;
this.area += gridXWidths[x] * gridYHeights[y];
}
}
}
}
}
public class Main {
public static void main(String[] args) throws IOException {
// 빠른 입출력을 위한 설정
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
int K = Integer.parseInt(st.nextToken());
List<Rectangle> rectangles = new ArrayList<>();
// 중복 자동 제거를 위해 Set 사용
Set<Integer> xSet = new HashSet<>();
Set<Integer> ySet = new HashSet<>();
// 1. 입력 받기 및 모든 좌표 수집
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
int id = i + 1;
int x1 = Integer.parseInt(st.nextToken());
int y1 = Integer.parseInt(st.nextToken());
int x2 = Integer.parseInt(st.nextToken());
int y2 = Integer.parseInt(st.nextToken());
rectangles.add(new Rectangle(id, x1, y1, x2, y2));
xSet.add(x1);
xSet.add(x2);
ySet.add(y1);
ySet.add(y2);
}
// 2. 좌표 압축 (Set -> List 변환 후 정렬)
List<Integer> xCoords = new ArrayList<>(xSet);
List<Integer> yCoords = new ArrayList<>(ySet);
Collections.sort(xCoords);
Collections.sort(yCoords);
// 3. 압축된 각 그리드 칸의 실제 가로/세로 길이 계산
long[] gridXWidths = new long[xCoords.size()];
long[] gridYHeights = new long[yCoords.size()];
for (int i = 0; i < xCoords.size() - 1; i++) {
gridXWidths[i] = xCoords.get(i + 1) - xCoords.get(i);
}
for (int i = 0; i < yCoords.size() - 1; i++) {
gridYHeights[i] = yCoords.get(i + 1) - yCoords.get(i);
}
// 4. 각 직사각형의 좌표를 그리드 좌표로 변환
for (Rectangle rect : rectangles) {
rect.setGridCoordinates(xCoords, yCoords);
}
// 5. 독점 영역 넓이 계산 (ID가 높은 순서부터)
boolean[][] used = new boolean[xCoords.size()][yCoords.size()];
for (int i = N - 1; i >= 0; i--) {
rectangles.get(i).calculateAndPaintArea(used, gridXWidths, gridYHeights);
}
// 6. 계산된 넓이 순으로 정렬 (넓이 내림차순, ID 오름차순)
rectangles.sort((r1, r2) -> {
if (r1.area != r2.area) {
return Long.compare(r2.area, r1.area); // 넓이 기준 내림차순
} else {
return Integer.compare(r1.id, r2.id); // ID 기준 오름차순
}
});
// 7. 상위 K개의 ID를 선택하여 오름차순으로 정렬 후 출력
List<Integer> resultIds = new ArrayList<>();
for (int i = 0; i < K; i++) {
resultIds.add(rectangles.get(i).id);
}
Collections.sort(resultIds);
StringBuilder sb = new StringBuilder();
for (int id : resultIds) {
sb.append(id).append(" ");
}
System.out.println(sb.toString().trim());
}
}