#include <queue>
#include <cstdio>
#include <vector>
#include <stdlib.h>
using namespace std;
typedef long long LL;
// =================== 代码实现开始 ========================
//Q:小根堆
priority_queue<LL,vector<LL>,greater<LL> > Q; //从小到大
// n: 初始点数
// k: 哈夫曼树的叉树
// w: w[i] 表示第i个点的点权
//返回值:最终编码的长度
LL solve(const vector<LL>& w, int n, int k)
{
LL sum = 0;
for(int i = 0; i < n; ++i )
Q.push(w[i]); //开始时,应进行的初始化操作(清零&插入)
if(k!=2){
int r = n%(k-1) == 1 ? 0 : k-n%(k-1); // r+ n = n*k + 1
n += r; //计算补零的个数并补零。
while(r--)
Q.push(0);
}
while(n>1) //终止条件?
{
LL newele = 0;
for(int i = 0; i < k; ++i)
{
newele += Q.top(); //找到权重最小的k个点并进行补零
Q.pop();
}
sum += newele;
Q.push(newele); //如何处理新产生的点
n -= k-1; //每次合并之后减少的点数是多少
}
return sum;
}
// ================== 代码实现结束 ======================
int main()
{
int n, k;
scanf("%d%d", &n, &k);
vector<LL> w;
w.reserve(n);
for (int i = 0; i < n; i++) {
LL a;
scanf("%lld", &a);
w.push_back(a);
}
printf("%lld\n", solve(w, n, k));
return 0;
}
重编码-k cs精英挑战营 Huffman树/编码构造
最新推荐文章于 2022-07-25 10:49:36 发布