题目链接:
http://www.lydsy.com/JudgeOnline/problem.php?id=4198
http://uoj.ac/problem/130
题解:
用一个堆来维护一个K叉哈夫曼树,如果无法合并(即n-1不为k-1的倍数时),就补充n-k个虚拟节点,节点的权值为0(不会影响结果),再合并即可。
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long LL;
const int inf = 1 << 26;
struct trees {
LL v, h;
};
bool operator<(trees a, trees b){
if(a.v != b.v) return a.v > b.v;
return a.h > b.h;
}
priority_queue<trees> q;
int n, k;
int main(){
scanf("%d %d", &n, &k);
for ( int i = 1; i <= n; i ++ ) {
trees a;
scanf("%lld", &a.v);
a.h = 1;
q.push(a);
}
LL top = 0;
if((n-1)%(k-1) != 0) top += k-1-(n-1)%(k-1); // 需要补为 0 的结点的个数
for ( int i = 1; i <= top; i ++ ) {
trees need;
need.v = 0; need.h = 1;
q.push(need);
}
top += n;
LL ans = 0;
while(top != 1) {
trees a;
LL temp = 0, mx = 0;
for ( int i = 1; i <= k; i ++ ) {
a = q.top(); temp += a.v;
mx = max(mx, a.h); q.pop();
}
ans += temp;
a.v = temp; a.h = mx+1;
q.push(a);
top -= k-1;
}
printf("%lld\n%lld\n", ans, q.top().h-1);
return 0;
}