석환이는 아기다. 아기 석환이는 자연수가 쓰여져있는 카드를 갖고 다양한 놀이를 하며 노는 것을 좋아한다. 오늘 아기 석환이는 무슨 놀이를 하고 있을까? 바로 카드 합체 놀이이다!
아기 석환이는 자연수가 쓰여진 카드를 n장 갖고 있다. 처음에 i번 카드엔 ai가 쓰여있다. 카드 합체 놀이는 이 카드들을 합체하며 노는 놀이이다. 카드 합체는 다음과 같은 과정으로 이루어진다.
아기 석환이는 수학을 좋아하긴 하지만, 아직 아기이기 때문에 점수를 얼마나 작게 만들 수 있는지를 알 수는 없었다(어른 석환이는 당연히 쉽게 알 수 있다). 그래서 문제 해결 능력이 뛰어난 여러분에게 도움을 요청했다. 만들 수 있는 가장 작은 점수를 계산하는 프로그램을 만들어보자.
첫 번째 줄에 카드의 개수를 나타내는 수 n(2 ≤ n ≤ 1,000)과 카드 합체를 몇 번 하는지를 나타내는 수 m(0 ≤ m ≤ 15×n)이 주어진다.
두 번째 줄에 맨 처음 카드의 상태를 나타내는 n개의 자연수 a1, a2, …, an이 공백으로 구분되어 주어진다. (1 ≤ ai ≤ 1,000,000)
첫 번째 줄에 만들 수 있는 가장 작은 점수를 출력한다.
카드를 계속 뽑고, 값을 다시 가장 작은 점수로 갱신해야 하므로 우선순위 큐를 사용해서 문제를 푼다. 문제 1번 조건에서 뽑은 두 카드는 값이 같지 않다고 주어져있으므로 (1) 두 카드가 같다면 다시 값 하나는 우선순위 큐에 넣고 하나는 빼낸다. (2) 문제 2번 조건에서 계산한 값을 x번 카드와 y번 카드 두장에 모두 덮어 써야하므로 더한 값을 우선순위 큐에 넣는 작업을 두 번 한다. (3) 그 후 우선순위 큐의 크기만큼 결과 값 sum에 우선순위 큐 값을 하나씩 빼내면서 더해가며 가장 작은 점수를 출력한다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
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 m = Integer.parseInt(st.nextToken());
PriorityQueue<Long> pq = new PriorityQueue<Long>();
st = new StringTokenizer(br.readLine());
for(int i=0; i<n; i++) {
pq.add(Long.parseLong(st.nextToken()));
}
for(int i=0; i<m; i++) {
long x = pq.poll();
long y = pq.poll();
if(x == y) { // (1)
pq.add(x);
y = pq.poll();
}
// (2)
pq.add(x+y);
pq.add(x+y);
}
long sum = 0;
int len = pq.size(); // (3)
for(int i=0; i<len; i++) { // (3)
sum += pq.poll();
}
System.out.println(sum);
}
}