문제 설명
접근법
- K개의 그룹을 만든다는 건 K-1개의 구간을 자른다는 것과 동일합니다.
[1, 3, 5, 6, 10]
에서 3개의 그룹을 만드는 건 [1 3 | 5 6 | 10]
과 같이 2개의 칸막이(|)를 설치하는 것과 동일합니다.
- 6과 10 사이에 칸막이를 설치하지 않으면 6과 10은 같은 그룹으로 묶입니다. 그렇게 되면 해당 그룹은 6과 10이 최소와 최대가 아니더라도 최소 4 이상의 점수를 가집니다.
[1 3 5 | 6 10 |]
-> 6과 10이 포함된 그룹은 4점
[1 3 | 5 6 10 |]
-> 6과 10이 포함된 그룹은 5점
[1 | 3 5 6 10 |]
-> 6과 10이 포함된 그룹은 7점
[| 1 3 5 6 10 |]
-> 6과 10이 포함된 그룹은 9점
그렇기 때문에 인접한 두 숫자의 차이가 큰 부분에 칸막이를 설치
하는 게 이득입니다.
- 저는 여러 구간을 표현할 때 list에 구간값을 모두 넣고 별도로 처음값과 끝값을 넣은 뒤 두개씩 꺼내는 방식을 선호합니다.
ex) [1,2,3,4,5,6,7,8,9,10]
에서 5~6사이, 그리고 1~2사이에 칸막이를 설치했다면 ([1|2,3,4,5|6,7,8,9,10]
) 구간값인 5,6,1,2 그리고 시작값과 끝값인 1,10을 list에 넣어 {5,6,1,2,1,10}을 만듭니다. 이를 정렬하면 {1,1,2,5,6,10}이 되고 여기서 2개씩 값을 꺼낸 1~1, 2~5, 6~10이 구간이 됩니다.
정답
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws Exception {
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());
int[] arr =new int[N];
st = new StringTokenizer(br.readLine());
for (int i = 0; i < N; i++) {
arr[i] = Integer.parseInt(st.nextToken());
}
PriorityQueue<int[]> pq = new PriorityQueue<int[]>((a,b)->b[2]-a[2]);
for (int i = 0; i < N-1; i++) {
pq.add(new int[] {arr[i],arr[i+1],Math.abs(arr[i]-arr[i+1])});
}
List<Integer> edgePoint = new LinkedList<Integer>();
edgePoint.add(arr[0]);
edgePoint.add(arr[N-1]);
int cnt = K-1;
while(--cnt>=0) {
int[] now = pq.poll();
edgePoint.add(now[0]);
edgePoint.add(now[1]);
}
Collections.sort(edgePoint);
int answer = 0;
while(!edgePoint.isEmpty()) {
int a = edgePoint.remove(0);
int b = edgePoint.remove(0);
answer += b-a;
}
System.out.println(answer);
}
}