[bzoj4198]荷马史诗
很容易想到哈夫曼树,容易扩展得到贪心:优先选最小的k个合并,堆维护即可
为了保证深度最小,可以加入深度权值,在权值相同时选择当前深度最小的即可
(注意:由于可能最后一次不足k个,那么显然可以将这些不足的放到最深的位置来减小答案,需要补上权值为0的点来保证每一次都有k个)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 struct ji{ 5 int d; 6 ll val; 7 bool operator < (const ji &k)const{ 8 return (val>k.val)||(val==k.val)&&(d>k.d); 9 } 10 }; 11 priority_queue<ji>q; 12 int n,k,x; 13 ll s,ans; 14 int main(){ 15 scanf("%d%d",&n,&k); 16 for(int i=1;i<=n;i++){ 17 scanf("%lld",&s); 18 q.push(ji{0,s}); 19 } 20 while ((n-1)%(k-1)){ 21 n++; 22 q.push(ji{0,0}); 23 } 24 while (n>1){ 25 x=s=0; 26 for(int i=1;i<=k;i++){ 27 s+=q.top().val; 28 x=max(x,q.top().d); 29 q.pop(); 30 } 31 ans+=s; 32 q.push(ji{x+1,s}); 33 n-=k-1; 34 } 35 printf("%lld\n%d",ans,q.top().d); 36 }