[NOI2015]荷马史诗

k叉哈夫曼树。

需要保证权值尽量小的前提下深度最小。

我们可以把k个节点合并成一个节点,最后合成一个。

所以如果n-1不是k-1的倍数,就补起来。最后就是先取k个最小的,用一个假的节点连起来,然后把这k个东西当成一个新的节点,节点的权值是k个点的权值和。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <algorithm>
#define int long long
using namespace std;
int n,k;
priority_queue<pair<int,int> ,vector<pair<int,int> >,greater<pair<int,int> > >q;
pair<int ,int>p;
signed main() {
    scanf("%lld%lld",&n,&k);
    for(int i=1;i<=n;i++) {
        scanf("%lld",&p.first);
        p.second=1;
        q.push(p);
    }
    if((n-1)%(k-1)) {
        for(int i=1;i<=k-1-(n-1)%(k-1);i++) q.push(make_pair(0,1));
        n+=k-1-(n-1)%(k-1);
    }
    int maxl=0,ans=0;
    while(q.size()^1) {
        int tp=0;
        for(int i=1;i<=k;i++) {
            tp+=q.top().first;maxl=max(maxl,q.top().second);q.pop();
        }
        ans+=tp;
        q.push(make_pair(tp,maxl+1));
    }
    cout<<ans<<endl<<q.top().second-1<<endl;return 0;
}
荷马史诗
我是咸鱼。转载博客请征得博主同意Orz
原文地址:https://www.cnblogs.com/sdfzhsz/p/9699822.html