Loading

P2168 [NOI2015] 荷马史诗 - 哈夫曼树

题解

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

由于哈夫曼树自下而上构造时,可能出现最顶层不满 \(k\) 个的情况,所以如果 \((n-1)\bmod (k-1)\neq 0\),需要补 \(k-1-((n-1)\bmod (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\n%d\n",ans,q.top().second);
	return 0;
}
posted @ 2021-10-01 12:03  Alan_Zhao_2007  阅读(40)  评论(0编辑  收藏  举报