哈夫曼树原理。
k=2时,和合并果子一样一样的。
由此思考,k>2时,应该也有相似的原理。确实如此,k进制哈夫曼树,每个结点最多会有k-1个子结点,对应k-1个元素(“元素”可以是更深层的子树),也就是说,每有k-1个元素被合并进去,新元素要想加进去,编码就得多一位。
推出算编码位数的方法后,剩下的就是处理一次合并多个果子的问题了。
1 /*by SilverN*/ 2 #include<iostream> 3 #include<algorithm> 4 #include<queue> 5 #include<cstring> 6 #include<cstdio> 7 #include<cmath> 8 using namespace std; 9 const int mxn=120000; 10 // 11 struct node{ 12 long long w;//出现频数 13 long long cnt;//位数 14 }; 15 bool operator < (node a,node b){//频数越大越优先 16 if(a.w!=b.w)return a.w>b.w; 17 return a.cnt>b.cnt; 18 } 19 priority_queue<node>q; 20 // 21 long long n,k; 22 long long w[mxn]; 23 long long ans=0; 24 int main(){ 25 scanf("%lld%lld",&n,&k); 26 int i,j; 27 for(i=1;i<=n;i++)scanf("%lld",&w[i]),q.push(node{w[i],1}); 28 int nl=0; 29 if((n-1)%(k-1))nl=(k-1)-((n-1)%(k-1)); 30 for(i=1;i<=nl;i++)q.push(node{0,1});//补位 31 nl+=n; 32 while(nl>1){//合并果子 33 long long a=0; 34 long long mxlen=0; 35 for(i=1;i<=k;i++){ 36 node now=q.top(); 37 q.pop(); 38 a+=now.w; 39 mxlen=max(mxlen,now.cnt); 40 } 41 q.push(node{a,mxlen+1}); 42 nl-=k-1; 43 ans+=a; 44 } 45 printf("%lld %lld",ans,q.top().cnt-1); 46 return 0; 47 }