【CF884D】Boxes And Balls k叉哈夫曼树
题目大意:给定一个大小为 N 的集合,每次可以从中挑出 2 个或 3 个数进行合并,合并的代价是几个数的权值和,求将这些数合并成 1 个的最小代价是多少。
引理:K 叉哈夫曼树需要保证 \((n-1)\%(k-1)=0\),在此基础上,每次取 K 个合并即可得到最小代价。
代码如下
#include <bits/stdc++.h>
using namespace std;
inline int read(){
int x=0,f=1;char ch;
do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch));
do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch));
return f*x;
}
int n;
long long ans,tmp;
priority_queue<long long,vector<long long>,greater<long long> >q;
void solve(){
n=read();
for(int i=1;i<=n;i++)q.push(read());
if(!(n&1))q.push(0),n++;
for(int i=n;i^1;i-=2)tmp=q.top(),q.pop(),tmp+=q.top(),q.pop(),tmp+=q.top(),q.pop(),q.push(tmp),ans+=tmp;
printf("%lld\n",ans);
}
int main(){
solve();
return 0;
}