求求求求
/*建哈夫曼树,以求最小值
利用哈夫曼树中权值越高(数据出现频率越高)的节点到根节点
的距离越小(对应哈夫曼编码越短)的性质,
将数据压缩成哈夫曼编码*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n,k;
ll n1,n2;
ll sum,maxh,cnt;
struct node{
ll w;//边权 长度
ll h;//该节点高度
};
bool operator < (node a,node b){
if(a.w!=b.w){
return a.w>b.w;//优先根据其长度排序
}
return a.h>b.h;//如果长度相等就按照高度排序
}
priority_queue<node> q;
int main(){
cin>>n>>k;
for(int i=1,x;i<=n;i++){
cin>>x;
q.push((node){x,1});//强制转换类型,边权和高度
}
if((n-1)%(k-1)){
cnt=k-1-(n-1)%(k-1);
//计算出需要填补的节点个数,为了把所有的点都连接构成树
}
for(int i=1;i<=cnt;i++){
q.push((node){0,1});//要补的节点与任意边的长度为0 不影响结果怕
}
while(q.size()!=1){
sum=0;
maxh=0;
for(int i=1;i<=k;i++){//操作:合并节点
sum+=q.top().w;//取队首的最小值合并
maxh=max(maxh,q.top().h);//找最小值
q.pop();
}
q.push((node){sum,maxh+1});//把合并后的节点再次放入队列
n1+=sum;//累加长度
n2=max(maxh,n2);//比较大小,找最短
}
cout<<n1<<endl<<n2<<endl;
return 0;
}