k叉哈夫曼树。
需要保证权值尽量小的前提下深度最小。
我们可以把k个节点合并成一个节点,最后合成一个。
所以如果n-1不是k-1的倍数,就补起来。最后就是先取k个最小的,用一个假的节点连起来,然后把这k个东西当成一个新的节点,节点的权值是k个点的权值和。

#include <iostream> #include <cstring> #include <cstdio> #include <cstdlib> #include <queue> #include <algorithm> #define int long long using namespace std; int n,k; priority_queue<pair<int,int> ,vector<pair<int,int> >,greater<pair<int,int> > >q; pair<int ,int>p; signed main() { scanf("%lld%lld",&n,&k); for(int i=1;i<=n;i++) { scanf("%lld",&p.first); p.second=1; q.push(p); } if((n-1)%(k-1)) { for(int i=1;i<=k-1-(n-1)%(k-1);i++) q.push(make_pair(0,1)); n+=k-1-(n-1)%(k-1); } int maxl=0,ans=0; while(q.size()^1) { int tp=0; for(int i=1;i<=k;i++) { tp+=q.top().first;maxl=max(maxl,q.top().second);q.pop(); } ans+=tp; q.push(make_pair(tp,maxl+1)); } cout<<ans<<endl<<q.top().second-1<<endl;return 0; }