#P3010. [NOIP 2004 提高组] 合并果子

[NOIP 2004 提高组] 合并果子

题目描述

在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。

每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过 n1n-1 次合并之后,就只剩下一堆了。多多在合并果子时总共消耗的体力等于每次合并所耗体力之和。

因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力。假定每个果子重量都为 11,并且已知果子的种类数和每种果子的数目,你的任务是设计出合并的次序方案,使多多耗费的体力最少,并输出这个最小的体力耗费值。

例如有 33 种果子,数目依次为 1,2,91, 2, 9。可以先将 1122 堆合并,新堆数目为 33,耗费体力为 33。接着,将新堆与原先的第三堆合并,又得到新的堆,数目为 1212,耗费体力为 1212。所以多多总共耗费体力 =3+12=15= 3 + 12 = 15。可以证明 1515 为最小的体力耗费值。

输入格式

共两行。

第一行是一个整数 nn,表示果子的种类数。

第二行包含 nn 个整数,用空格分隔,第 ii 个整数 aia_i 是第 ii 种果子的数目。

输出格式

一个整数,也就是最小的体力耗费值。输入数据保证这个值小于 2312^{31}

样例输入1

3
1 2 9

样例输出1

15

样例输入2

1
1

样例输出2

0

样例输入3

2
5 7

样例输出3

12

数据范围

  • 对于 30%30\% 的数据,保证有 n103n \le 10^3
  • 对于 50%50\% 的数据,保证有 n5×103n \le 5 \times 10^3
  • 对于全部的数据,保证有 1n1041 \le n \le 10^41ai2×1041 \le a_i \le 2 \times 10^4
  • 输入数据保证答案小于 2312^{31}

说明

题目来源:Luogu P1090 [NOIP 2004 提高组] 合并果子,改编为标准输入输出,数据为随机生成并经双标程(C++ / Python)与精确子集 DP 交叉校验。

提示

经典 Huffman 贪心,时间复杂度 O(nlogn)O(n \log n)

  1. 用一个小根堆维护当前所有果堆的重量;
  2. 每次取出重量最小的两堆合并,将新堆(重量为两者之和)重新入堆,并把合并代价累加;
  3. 重复直到只剩一堆,累加的代价即为答案。

贪心正确性:每次合并最小的两堆,可以保证总代价最小(Huffman 树最优性)。注意 n=1n = 1 时不需要任何合并,答案为 00