P2168 [NOI2015] 荷马史诗

题解

其实就是构造一个 (k)哈夫曼树,并在保证 (sum w_i imes dep_i) 最小的情况下使得树的深度最小。

由于哈夫曼树自下而上构造时,可能出现最顶层不满 (k) 个的情况,所以如果 ((n-1)mod (k-1) eq 0),需要补 (k-1-((n-1)mod (k-1))) 个虚点,使得最底层而不是最顶层不满 (k) 个。

代码
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <utility>
#include <queue>
using namespace std;
#define For(Ti,Ta,Tb) for(int Ti=(Ta);Ti<=(Tb);++Ti)
#define Dec(Ti,Ta,Tb) for(int Ti=(Ta);Ti>=(Tb);--Ti)
template<typename T> void Read(T &_x){
	_x=0;int _f=1;
	char ch=getchar();
	while(!isdigit(ch)) _f=(ch=='-'?-1:_f),ch=getchar();
	while(isdigit(ch)) _x=_x*10+(ch^48),ch=getchar();
	_x*=_f;
}
template<typename T,typename... Args> void Read(T &_x,Args& ...others){
	Read(_x);Read(others...);
}
typedef long long ll;
typedef pair<ll,int> pii;
const int N=1e5+5;
int n,k;ll w[N];
priority_queue<pii,vector<pii>,greater<pii>> q;
int main(){
	Read(n,k);
	For(i,1,n){
		Read(w[i]);q.push({w[i],0});
	}
	int cnt=(n-1)%(k-1)?k-1-(n-1)%(k-1):0;
	For(i,1,cnt) q.push({0,0});
	ll ans=0;
	while(q.size()>1){
		ll w=0,h=0;
		For(i,1,k){
			pii x=q.top();q.pop();
			w+=x.first,h=max(h,ll(x.second));
		}
		ans+=w,q.push({w,h+1});
	}
	printf("%lld
%d
",ans,q.top().second);
	return 0;
}
Written by Alan_Zhao
原文地址:https://www.cnblogs.com/alan-zhao-2007/p/p2168-sol.html