4198: [Noi2015]荷马史诗

题目链接

题目大意:一篇文章有n个单词,其中第i个单词的出现次数为w[i]。你要用k进制串s[i]替换第i种单词。要求:对于任意i!=j,都有s[i]不是s[j]的前缀。
要使替换后的文章总长度最小。
求这个最小总长度。
在这个前提下,要使s[i]的最大长度最短,求这个最短的长度

题解:k叉哈夫曼树
取最小的k个合并即可
发现只有当(n-1)%(k-1)=0的时候才能恰好合并,所以要添加k-1-(n-1)%(k-1)个权值为0高度为1的虚拟节点
用堆维护就好了

为了保证最大高度最小,把高度加成第二关键字

我的收获:姿势++

#include <bits/stdc++.h>
using namespace std; 

#define ll long long

ll n,k,ans;

struct node{
    ll val,dep;
    node(){}
    node(ll _,ll __){val=_,dep=__;}
}tmp;

bool operator <(node x,node y){return x.val>y.val||(x.val==y.val&&x.dep>y.dep);}

priority_queue<node> q;

ll readin()
{
    ll x=0;char ch=getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+(ll)(ch-'0'),ch=getchar();
    return x;
}

void work()
{
    while(n>1){
        ll maxd=0,tot=0;
        for(ll i=1;i<=k;i++){
            tmp=q.top();q.pop();
            tot+=tmp.val;
            maxd=max(maxd,tmp.dep);
        }  
        q.push(node(tot,maxd+1));
        ans+=tot;n-=k-1;
    }
    printf("%lld\n%lld\n",ans,q.top().dep-1);
}

void init()
{
    n=readin();k=readin();
    for(ll i=1;i<=n;i++) q.push(node(readin(),1));
    ll remain=(n-1)%(k-1);
    if(remain!=0) remain=k-1-remain,n+=remain;
    for(ll i=1;i<=remain;i++) q.push(node(0,1));
}

int main()
{
    init();
    work();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值