BZOJ4198或UOJ130 荷馬史詩 【K叉哈夫曼樹】【堆】
阿新 • • 發佈:2019-02-05
題解:
用一個堆來維護一個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;
}