문제풀이/백준

[백준]10800: 컬러볼 - JAVA

빈둥벤둥 2021. 9. 14. 18:05

[백준]10800: 컬러볼

 

10800번: 컬러볼

첫 줄에는 공의 개수를 나타내는 자연수 N이 주어진다(1 ≤ N ≤ 200,000). 다음 N개의 줄 중 i번째 줄에는 i번째 공의 색을 나타내는 자연수 Ci와 그 크기를 나타내는 자연수 Si가 주어진다(1 ≤ Ci ≤ N

www.acmicpc.net

풀이

🪑 누적합, 투포인터 유형의 문제로 풀이 과정을 생각해 내기가 어려웠지만 재미있는 문제였다.

 

📝 문제를 정리해 보자!

  • 각각의 플레이어는 자신의 공 색과 다른 색의 공 중에서 크기가 작은 공을 사로잡을 수 있다.
  • 각 플레이어가 사로잡을 수 있는 모든 공들의 크기 합을 출력한다.
  • 공의 색은 1~N의 경우의수가 존재한다.

 

 

🔧 문제 푸리

  1. 입력 받은 공의 인덱스, 색, 크기 정보를 저장하여 크기 순으로 정렬한다.
  2. 공을 하나씩 탐색하며 값을 계산해 준다. 이때 현재 탐색하는 공 번호에 해당하는 결과값은 현재까지 계산한 자신보다 작은 공 크기의 합에서 같은 색 공의 크기를 빼 주면 된다. 
  3. 인덱스 순서대로 결과를 출력한다.

 

 

🔹 공의 인덱스, 색, 크기 정보를 저장하여 크기 순으로 정렬한다.

  • 크기가 작은 공 부터 탐색을 할 것이다.
  • 크기가 큰 공에서 현재까지 계산된 값을 빼 주기 위함이다.

 

 

🔹 공을 하나씩 탐색하며 값을 계산해 준다. 이때 현재 탐색하는 공 번호에 해당하는 결과값은 현재까지 계산한 자신보다 작은 공 크기의 합에서 같은 색 공의 크기를 빼 주면 된다. 

  • 정렬된 공의 정보를 순서대로 확인하며 탐색한다.
  • 구하고자 하는 값은 자신의 공보다 크기가 작으며 색이 다른 공의 크기의 합이다.
  • 그러므로 크기 순서대로 정렬되어있는 상태에서 현재 공 보다 작은 공의 크기를 누적하여 더한 값에서 같은 색의 공 크기의 합을 빼 주면 된다.
  • 같은 색의 공 크기의 합을 저장할 배열과 결과 정보를 저장할 배열이 필요하다.
  • 이때 현재 공 보다 작은 공의 인덱스를 기억할 변수를 생성해 주고, 반복문을 돌며 현재 공 보다 작은 공의 크기의 합을 누적하여 준다.
  • 누적하는 과정에서 색상별 공 크기의 합도 함께 누적하여 준다.
  • 현재 공의 인덱스에 해당하는 결과 값은 앞서 계산해준 값들을 활용하면 된다. 누적하여 더한 합에서 현재 공과 같은 색의 공의 누적합을 빼 준다.

 

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
//10800: 컬러볼
import java.io.*;
import java.util.*;
 
public class Main {
    public static void main(String[] args) throws IOException {
        //입력
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(bf.readLine());
 
        Ball[] balls = new Ball[n];
        for(int i = 0; i < n; i++) {
            String str = bf.readLine();
            StringTokenizer st = new StringTokenizer(str);
            int c = Integer.parseInt(st.nextToken());
            int s = Integer.parseInt(st.nextToken());
            balls[i] = new Ball(i, c, s);
        }   
        //입력 끝
        Arrays.sort(balls, (o1, o2) -> o1.size - o2.size);
 
        int[] result = new int[n];
        int[] colors = new int[n + 1];
        int ball_idx = 0;
        int sum = 0;
        for(int i = 0; i < n; i++) {
            Ball current = balls[i];
            while(balls[ball_idx].size < current.size) {
                sum += balls[ball_idx].size;
                colors[balls[ball_idx].color] += balls[ball_idx].size;
                ball_idx++;
            }
            result[current.idx] = sum - colors[current.color]; 
        }
        
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < n; i++) {
            sb.append(result[i] + "\n");
        }
        System.out.print(sb.toString());
    }
 
    public static class Ball {
        int idx, color, size;
 
        public Ball(int idx, int color, int size) {
            this.idx = idx;
            this.color = color;
            this.size = size;
        }
    }
}
 
cs