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());
    }
}

results matching ""

    No results matching ""