[UOJ#130][BZOJ4198][Noi2015]荷马史诗

试题描述

追逐影子的人,自己就是影子。 ——荷马

Allison 最近迷上了文学。她喜欢在一个慵懒的午后,细细地品上一杯卡布奇诺,静静地阅读她爱不释手的《荷马史诗》。但是由《奥德赛》和《伊利亚特》组成的鸿篇巨制《荷马史诗》实在是太长了,Allison 想通过一种编码方式使得它变得短一些。
一部《荷马史诗》中有 n 种不同的单词,从 1 到 n 进行编号。其中第 i 种单词出现的总次数为 wi。Allison 想要用 k 进制串 si 来替换第 i 种单词,使得其满足如下要求:
对于任意的 1≤i,j≤n,i≠j,都有:si 不是 sj 的前缀。
现在 Allison 想要知道,如何选择 si,才能使替换以后得到的新的《荷马史诗》长度最小。在确保总长度最小的情况下,Allison 还想知道最长的 si 的最短长度是多少?
一个字符串被称为 k 进制字符串,当且仅当它的每个字符是 0 到 k−1 之间(包括 0 和 k−1)的整数。
字符串 Str1 被称为字符串 Str2 的前缀,当且仅当:存在 1≤t≤m,使得 Str1=Str2[1..t]。其中,m 是字符串 Str2 的长度,Str2[1..t] 表示 Str2 的前 t 个字符组成的字符串。

输入

输入文件的第 1 行包含 2 个正整数 n,k,中间用单个空格隔开,表示共有 n 种单词,需要使用 k 进制字符串进行替换。

接下来 n 行,第 i+1 行包含 1 个非负整数 wi,表示第 i 种单词的出现次数。

输出

输出文件包括 2 行。

第 1 行输出 1 个整数,为《荷马史诗》经过重新编码以后的最短长度。
第 2 行输出 1 个整数,为保证最短总长度的情况下,最长字符串 si 的最短长度。

输入示例


输出示例


数据规模及约定

对于所有数据,保证 2≤n≤100000,2≤k≤9。

题解

这题没啥好说的,k 进制 Huffman 编码。

注意当 (n-1) mod (k-1) > 0 时,需要补 0,因为最终的 Huffman 树(其实就是 Trie 树)必须是一个满 k 叉树。

题目还要求最大深度最小,那么堆中比较大小的规则补充一下:当权重相同时,优先取深度更小的子树。

证明见算导(算导上只有二叉树的证明,但是 k 叉树的证明同理),核心思路就是先证最优编码一定对应一个满二叉树,再证每个集合中出现频率最小的两个元素一定放在最深层,并且二进制编码只差最后一位(即它们在树上是兄弟关系)。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <queue>
using namespace std;
#define LL long long const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *Tail;
inline char Getchar() {
if(Head == Tail) {
int l = fread(buffer, 1, BufferSize, stdin);
Tail = (Head = buffer) + l;
}
return *Head++;
}
LL read() {
LL x = 0, f = 1; char c = Getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
return x * f;
} #define maxn 100010 struct Node {
LL val; int mxd;
Node() {}
Node(LL _, int __): val(_), mxd(__) {}
bool operator < (const Node& t) const { return val != t.val ? val > t.val : mxd > t.mxd; }
};
priority_queue <Node> Heap; int n, K; int main() {
n = read(); K = read();
for(int i = 1; i <= n; i++) Heap.push(Node(read(), 0));
while((n - 1) % (K - 1)) Heap.push(Node(0, 0)), n++; LL ans = 0;
while(Heap.size() > 1) {
LL sumv = 0; int mxd = 0;
for(int c = 1; c <= K && !Heap.empty(); c++) {
Node u = Heap.top(); Heap.pop();
sumv += u.val; mxd = max(mxd, u.mxd);
}
ans += sumv; mxd++;
Heap.push(Node(sumv, mxd));
}
printf("%lld\n%d\n", ans, Heap.top().mxd); return 0;
}

[UOJ#130][BZOJ4198][Noi2015]荷马史诗的更多相关文章

  1. [BZOJ4198][Noi2015]荷马史诗

    4198: [Noi2015]荷马史诗 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 700  Solved: 365[Submit][Status] ...

  2. [BZOJ4198] [Noi2015] 荷马史诗 (贪心)

    Description 追逐影子的人,自己就是影子. ——荷马   Allison 最近迷上了文学.她喜欢在一个慵懒的午后,细细地品上一杯卡布奇诺,静静地阅读她爱不释手的<荷马史诗>.但是 ...

  3. BZOJ4198: [Noi2015]荷马史诗(哈夫曼树)

    Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1824  Solved: 983[Submit][Status][Discuss] Descripti ...

  4. 【BZOJ4198】[Noi2015]荷马史诗 贪心+堆

    [BZOJ4198][Noi2015]荷马史诗 Description 追逐影子的人,自己就是影子. ——荷马 Allison 最近迷上了文学.她喜欢在一个慵懒的午后,细细地品上一杯卡布奇诺,静静地阅 ...

  5. BZOJ_4198_[Noi2015]荷马史诗_huffman实现

    BZOJ_4198_[Noi2015]荷马史诗_huffman实现 题意: Allison 最近迷上了文学.她喜欢在一个慵懒的午后,细细地品上一杯卡布奇诺,静静地阅读她爱不释手的<荷马史诗> ...

  6. 洛谷 P2168 [NOI2015]荷马史诗 解题报告

    P2168 [NOI2015]荷马史诗 题目描述 追逐影子的人,自己就是影子 --荷马 Allison 最近迷上了文学.她喜欢在一个慵懒的午后,细细地品上一杯卡布奇诺,静静地阅读她爱不释手的<荷 ...

  7. BZOJ4198 & 洛谷2168 & UOJ130:[NOI2015]荷马史诗——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4198 https://www.luogu.org/problemnew/show/P2168 ht ...

  8. bzoj 4198: [Noi2015]荷马史诗

    Description 追逐影子的人,自己就是影子. --荷马 Allison 最近迷上了文学.她喜欢在一个慵懒的午后,细细地品上一杯卡布奇诺,静静地阅读她爱不释手的<荷马史诗>.但是由& ...

  9. [Noi2015]荷马史诗

    来自FallDream的博客,未经允许,请勿转载,谢谢. 追逐影子的人,自己就是影子. ——荷马 Allison 最近迷上了文学.她喜欢在一个慵懒的午后,细细地品上一杯卡布奇诺,静静地阅读她爱不释手的 ...

随机推荐

  1. SQL Server 2008 转换为 SQL 2005 数据库 脚本生成

    Tips: 本文讨论如何把数据库从SQL Server 2008版本降低到2005,因为在本地开发是以SQL Server 2008 Express Edition版本进行的,而主机提供商现在提供的M ...

  2. 【笨办法学Python】习题11:打印出改变了的输入

    print "How old are you?", age = raw_input() print "How tall are you?", height = ...

  3. POJ 3140 Contestants Division (树形DP,简单)

    题意: 有n个城市,构成一棵树,每个城市有v个人,要求断开树上的一条边,使得两个连通分量中的人数之差最小.问差的绝对值.(注意本题的M是没有用的,因为所给的必定是一棵树,边数M必定是n-1) 思路: ...

  4. 1.JOIN和UNION区别

    1.JOIN和UNION区别join 是两张表做交连后里面条件相同的部分记录产生一个记录集,union是产生的两个记录集(字段要一样的)并在一起,成为一个新的记录集 . JOIN用于按照ON条件联接两 ...

  5. 如何在Ubuntu 16.04上安装Apache Web服务器

    转载自:https://www.howtoing.com/how-to-install-the-apache-web-server-on-ubuntu-16-04 介绍 Apache HTTP服务器是 ...

  6. stringstream clear与str("")的问题

    一.str与clear函数 C++Reference对于两者的解释: 可见:clear()用来设置错误状态,相当于状态的重置:str用来获取或预置内容 二.区别 运行下面测试代码: #include& ...

  7. 作用域插槽 向父组件传递 <template slot-scope="{ row, index }" slot="dateNo">

    作用域插槽 向父组件传递 <template slot-scope="{ row, index }"  slot="dateNo"> slotTes ...

  8. java script DOM BOM

    onclick        当用户点击某个对象时调用的事件句柄.ondblclick     当用户双击某个对象时调用的事件句柄. onfocus        元素获得焦点.            ...

  9. https 调用验证失败 peer not authenticated

    https 调用验证失败 peer not authenticated 报错日志: Caused by: javax.net.ssl.SSLPeerUnverifiedException: peer ...

  10. shell脚本,逻辑结构题练习。

    awk '/5/{a=1}!a' file2结果:1234解释:第一行 /5/不匹配跳过{a=1},继续!a,此时a没有值属于假取反为真,故输出第一行 第二行 /5/不匹配跳过{a=1},继续!a,此 ...