单词出现次数即Huffman树叶子结点权值,求出k叉Huffman树
权值相同时优先深度最小(已合并次数最少)的合并
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<vector>
#include<algorithm>
#define op < //小根堆
using namespace std;
typedef long long ll;
const int N=1e5+5;
struct Pair{
ll i,j;
Pair(){}
Pair(ll i,ll j):i(i),j(j){};
bool operator op(const Pair&t)const{
return i==t.i?j<t.j:i<t.i;
}
}heap[N],tmp;
struct Binary_heap{
int sz;
void up(int p){
while(p>1&&heap[p] op heap[p>>1])swap(heap[p],heap[p>>1]),p>>=1;
}
void push(ll i,ll j){
heap[++sz]=Pair(i,j);
up(sz);
}
void down(int p){
int ls=p<<1;
while(ls<=sz){
if(ls<sz&&heap[ls|1] op heap[ls])ls|=1;
if(heap[ls] op heap[p])swap(heap[ls],heap[p]),p=ls,ls=p<<1;
else break;
}
}
void pop(){
heap[1]=heap[sz--];
down(1);
}
Pair top(){
return heap[1];
}
}P;
int n,k;
ll ans,len,cnt;
int main(){
P.sz=0;
scanf("%d%d",&n,&k);
for(int i=0;i<n;++i)scanf("%lld",&cnt),P.push(cnt,0);
int res=(n-1)%(k-1);
if(res)res=k-1-res;
while(res--)P.push(0,0);
while(P.sz>1){
ll dep=0,tot=0;
for(int i=0;i<k;++i)tmp=P.top(),P.pop(),tot+=tmp.i,dep=max(dep,tmp.j);
P.push(tot,dep+1);
ans+=tot;
}
printf("%lld\n%lld\n",ans,P.top().j);
return 0;
}