题解:哈夫曼树
先补全节点,以总个数为第一关键字,高度为第二关键字,求哈夫曼树即可
问题:不明白哈夫曼树的原理及证明
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; typedef long long Lint; const int maxn=100009; int n,m; Lint anssum,ansh; int nn; Lint sum[maxn<<2]; Lint h[maxn<<2]; struct Point{ int x; bool operator < (const Point &rhs) const{ if(sum[x]==sum[rhs.x]){ return h[x]>h[rhs.x]; }else{ return sum[x]>sum[rhs.x]; } } Point(int xx){ x=xx; } Point(){} }; priority_queue<Point>q; int main(){ scanf("%d%d",&n,&m); while(!q.empty())q.pop(); for(int i=1;i<=n;++i){ scanf("%lld",&sum[i]); h[i]=0; q.push(Point(i)); } nn=n; if(m!=2){ for(int l=1;;++l){ if((m-1)*l+1>=n){ for(int i=n+1;i<=(m-1)*l+1;++i){ sum[++nn]=0;h[nn]=0; q.push(Point(i)); } break; } } } while(q.size()!=1){ ++nn; for(int i=1;i<=m;++i){ int t=q.top().x;q.pop(); h[nn]=max(h[nn],h[t]+1); sum[nn]+=sum[t]; } ansh=max(ansh,h[nn]); anssum=anssum+sum[nn]; q.push(Point(nn)); } printf("%lld ",anssum); printf("%lld ",ansh); return 0; }