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;
}
發佈了86 篇原創文章 · 獲贊 6 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章