bzoj4198 [Noi2015]荷马史诗 k叉哈夫曼树

k叉哈夫曼树
二叉就是贪心,找最小的两个合并,想当年记得是用。。两个数组存的吧。。只是tooyoungtoosimple。。虽然是O(n),优先级队列O(nlogn)。。
k叉的是添加x个w值为0节点,使得最后组成的是每个节点要么是叶子,要么是有k个儿子,数学(?)推导一下即可。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
#define ll long long
using namespace std;
struct node{
    ll val;int len;
    bool operator < (const node &x)const{
        return x.val<val||(x.val==val&&x.len<len);
    }
};
int n,k,anslen=0;ll ansval=0;
priority_queue<node>huff;
int main(){
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++){
        ll x;
        scanf("%lld",&x);
        huff.push((node){(ll)x,1});
    }
    int t=(((n-1)/(k-1)+1)*(k-1)+1-n)%(k-1);
    for(int i=1;i<=t;i++) huff.push((node){(ll)0,1});
    while(!huff.empty()){
        int len=0;ll val=0;
        for(int i=1;i<=k;i++){
            node x=huff.top();
            huff.pop();
            val+=x.val;len=max(len,x.len);
        }
        if(!huff.empty()) {
            len++;
            huff.push((node){(ll)val,len});
        }
        ansval+=val;anslen=len;
    }
    printf("%lld\n%d\n",ansval,anslen);
    return 0;
}
发布了87 篇原创文章 · 获赞 7 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/yxr0105/article/details/51416636
今日推荐