重编码-K

重编码-K


背景

小粽学习了哈夫曼树之后,自己设计了贪心算法,用两个队列就过掉了练习题

小粽想:那堆的算法有什么用呢?为了解决小粽的疑惑,邓老师委托小莉命制了这道题目……

描述

有一篇文章,文章包含 nn 种单词,单词的编号从 11 至 nn,第 ii 种单词的出现次数为 wiwi。

现在,我们要用一个 kk 进制串(即只包含 0,1,...,k−10,1,...,k-1 的串) sisi 来替换第 ii 种单词,使其满足如下要求:对于任意的 1≤i<j≤n1≤i<j≤n,都有 sisi 不是 sjsj 的前缀(这个要求是为了避免二义性)。

你的任务是对每个单词选择合适的 sjsj,使得替换后的文章总长度(定义为所有单词出现次数替换它的 kk 进制串的长度乘积的总和)最小。求这个最小长度。

字符串 S1S1(不妨假设长度为 nn)被称为字符串 S2S2 的前缀,当且仅当:S2S2 的长度不小于 nn,且 S1S1 与 S2S2 前 nn 个字符组组成的字符串完全相同。

输入格式

第一行一个整数 nn,表示单词种数。

第 2 行到第 n+1n+1 行,第 i+1i+1 行包含一个正整数 wiwi,表示第 ii 种单词的出现次数。

输出格式

表示整篇文章重编码后的最短长度

输入样例1

5 3
1
3
5
10
3

输出样例1

29

样例2

点此下载。

限制

对于 100% 的数据,满足 1≤n≤3×105,2≤k≤10,1≤wi≤1091≤n≤3×105,2≤k≤10,1≤wi≤109;

对于 40% 的数据,满足 n≤3000n≤3000;

对于 35% 的数据,满足 k=2k=2。

 

 

#include <queue>
#include <cstdio>
#include <stdlib.h>
#include <vector>

using namespace std;

typedef long long ll;
priority_queue<ll, vector<ll>, greater<ll> > Q;

// n: 初始点数
// k: 哈夫曼树的叉树
// w: w[i] 表示第i个点的点权
// 返回值:最终编码的长度
ll solve(const vector<ll>& w, int n, int k)
{
    ll sum = 0;
    for (int i = 0; i < n; ++i)
        Q.push(w[i]);

    if(k!=2){
    int r = n%(k-1)==1 ? 0 : k-n%(k-1);
    n += r;
    while(r--)
        Q.push(0);}

    while(n>1)
    {
        ll newEle = 0;
        for (int i = 0; i < k; ++i)
        {
            newEle += Q.top();
            Q.pop();
        }
        sum += newEle;
        Q.push(newEle);

        n -= k-1;
    }

    return sum;

}


int main()
{
    int n, k;
    scanf("%d%d", &n, &k);

    vector<ll> w;
    w.reserve(n);
    for (int i = 0; i < n; i++)
    {
        ll a;
        scanf("%lld", &a);
        w.push_back(a);
    }

    printf("%lld\n", solve(w, n, k));
    return 0;
}

!!!注意K叉树K!=2时可能需要补0,否则结果不是最小。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值