题解:http://blog.csdn.net/cqbzwja/article/details/46974241
k叉哈夫曼树.
NOI模拟赛当场AC的唯一一题真是感动233
AC code:
#include <cstdio>
#include <queue>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll N=1000010;
ll n,k,ans1,ans2,fin_ans1=-1,fin_ans2;
ll w[N];
struct Data{
ll val,cnt;
Data() {}
Data(ll val,ll cnt):val(val),cnt(cnt) {}
friend bool operator<(Data x,Data y){
if(x.val!=y.val) return x.val>y.val;
return x.cnt>y.cnt;
}
};
priority_queue<Data> Q;
void merge(){
ll m=min((ll)Q.size(),k),n_tot=0,maxcnt=0;
Data d=Data(0,0);
Data a[10];
for(ll i=1;i<=m;i++){
a[i]=Q.top();
Q.pop();
d.val+=a[i].val;
if(a[i].val) n_tot++;
if(a[i].cnt>maxcnt) maxcnt=a[i].cnt;
}
if(n_tot>1) d.cnt=maxcnt+1;
else{
ans1-=d.val;
d.cnt=maxcnt;
}
ans1+=d.val;
Q.push(d);
}
void work(){
ans1=0;
while(Q.size()!=1) merge();
ans2=Q.top().cnt;
if(fin_ans1==-1||fin_ans1>ans1||(fin_ans1==ans1&&fin_ans2>ans2)){
fin_ans1=ans1;
fin_ans2=ans2;
}
}
int main(){
scanf("%lld%lld",&n,&k);
for(ll i=1;i<=n;i++) scanf("%lld",&w[i]);
for(int i=0;i<=k-2;i++){
for(int j=1;j<=n;j++) Q.push(Data(w[j],0));
for(int j=1;j<=i;j++) Q.push(Data(0,0));
work();
while(!Q.empty()) Q.pop();
}
printf("%lld\n%lld\n",fin_ans1,fin_ans2);
return 0;
}