bzoj 4198: [Noi2015]荷马史诗【哈夫曼树+贪心】

和合并果子类似(但是是第一次听说哈夫曼树这种东西)
做法也类似,就是因为不用知道树的形态,所以贪心的把最小的k个点合为一个节点,然后依次向上累加即可,具体做法同合并果子(但是使用优先队列
注意这里可能不能被k-1整除,需要补一些出现次数0的单词

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
int N=100005;
long long n,k,con;
long long ans;
struct qwe
{
	long long l,h;
	qwe(long long L=0,long long H=0)
	{
		l=L,h=H;
	}
	bool operator < (const qwe &a) const
	{
		return l>a.l||(l==a.l&&h>a.h);
	}
};
priority_queue<qwe>q;
long long read()
{
	long long r=0,f=1;
	char p=getchar();
	while(p>'9'||p<'0')
	{
		if(p=='-')
			f=-1;
		p=getchar();
	}
	while(p>='0'&&p<='9')
	{
		r=r*10+p-48;
		p=getchar();
	}
	return r*f;
}
int main()
{
	con=n=read(),k=read();
	for(long long i=1;i<=n;i++)
	{
		long long x=read();
		q.push(qwe(x,1));
	}
	if((n-1)%(k-1))
		con+=k-1-(n-1)%(k-1);
	for(long long i=1;i<=con-n;i++)
		q.push(qwe(0,1));
	while(con>1)
	{
		long long sum=0,mx=0;
		for(long long i=1;i<=k;i++)
		{
			sum+=q.top().l;
			mx=max(mx,q.top().h);
			q.pop();
		}
		ans+=sum;
		q.push(qwe(sum,mx+1));
		con-=k-1;
	}
	printf("%lld\n%lld\n",ans,q.top().h-1);
	return 0;
}
posted @ 2018-07-31 23:07  lokiii  阅读(151)  评论(0编辑  收藏  举报