アルゴリズム競争の高度なガイド--- 0x17(バイナリヒープ)Homer Epic

トピック

ここに画像の説明を挿入

回答

  1. ハフマンツリーの適用には、マージ後の最小重量が必要であり、高さはできるだけ低くする必要があります
  1. k個の数値の組み合わせごとに、毎回組み合わせる最小のk個の数値である必要があります。図に示すように、最終的な重みを最小(特定の数値)にする必要があるため、下部の数値が最大の重みになります。の場合)、次に、小さい重みでより多くの寄与を行い、大きな重みでより少ない寄与を行う必要があります。これはハフマンツリーですが、kの組み合わせごとに、最後にマージされる図の状況が発生する可能性があります。 1.層の数が十分でないkの場合、ノード1、2、3、4、5のいずれかを現在の重みよりも小さい最後の層に移動するため、この操作は最小ではありません。ハフマンツリーを変更できます。埋めるには、ノードの数を、それらをマージできる範囲で正確に増やすことです。増やしたノードの値は0に設定され、結果は最終的に影響を受けません。
    ここに画像の説明を挿入
  1. 2番目の要件では、同じ重みが複数ある場合、現在の局所最適解を保証できるように、マージされた高さを小さくする必要があります。そのため、最初のキーとして重みを直接使用し、2番目のキーとして高さを使用します。ソートされる

コード

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>

using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
const int N = 1e5 + 10;

ll n, k;
ll w[N];

int main() {
    
    

    cin >> n >> k;
    priority_queue<PLL, vector<PLL>, greater<PLL>> heap;

    for (int i = 1; i <= n; i++) {
    
    
        cin >> w[i];
        heap.push({
    
    w[i], 0});
    }

    while ((n - 1) % (k - 1)) {
    
    
        heap.push({
    
    0ll, 0});
        n++;
    }

    ll res = 0;
    while (heap.size() > 1) {
    
    
        ll s = 0;
        ll h = 0;
        for (int i = 1; i <= k; i++) {
    
    
            auto x = heap.top();
            heap.pop();
            s += x.first;
            h = max(h, x.second);
        }
        res += s;
        heap.push({
    
    s, h + 1});
    }
    cout << res << "\n" << heap.top().second << endl;
    return 0;
}


おすすめ

転載: blog.csdn.net/qq_44791484/article/details/113851671