比较简单,这道题需要贪心解决。

不需要任何复杂的数据结构,一个luo的堆就足够了。

本题的意思就是:给定n种单词及在文本中各自出现的频率,要求利用二进制串对其进行前缀编码,使得压缩后的文本长度最短。

改用k进制串?最长的单个单词编码最短?

我们知道有个叫huffman编码的东西就是来解决这类编码问题的。所以尝试用huffman思想去解题。

如果编码的进制是2进制就好了,但是题目的数据只有少部分是2进制编码的,

所以我们要仿造二叉形式huffman一次弹出两个(最小值)成k叉一次弹出k个(最小值);

二叉堆来实现(不是用k叉堆,这样做时间复杂度太高且不易实现)

每一次弹出最值时就是连续取二叉堆的前k个数就可以了。

堆中保存Huffman树中串出现频率和,以及Huffman树的深度;

比较时先比较频率和,再比较深度(不可不比,要保证Huffman树高最小);

每次合并时,ans都要加上合并后长度(要不然求的是串频率和),而深度在取最大后再插入时要加1;

当堆中只有一个元素时退出,这时,ans和该元素深度即为答案;

注意到初始化堆的时候最后一层到不了k个怎么办?

初始化时注意各元素深度为0,若n!≡1mod(k-1),那么补齐n,增加的新元素频率为0(显然),深度为0;

堆的建立就不详细说了。

uses math;
const maxn=;
type rec=record
num,deep:int64;
end;
var n,k,i,j,tot:longint;ans,mxdep:int64;
node,now:rec;
a:array[..maxn]of int64;
q:array[..maxn]of rec;
procedure swap(var a,b:rec);
var t:rec;
begin
t:=a; a:=b; b:=t;
end;
procedure up(x:longint);
begin
while x> do begin
if (q[x].num>q[x div ].num)or((q[x].num=q[x div ].num)and(q[x].deep>q[x div ].deep))//注意多判断深度
then break;
swap(q[x],q[x div ]);
x:=x div ;
end;
end;
procedure down(x:longint);
var lson,rson,son,pd:longint;
begin
while x<tot do begin
lson:=*x; //pd=;
rson:=*x+; //pd=;
pd:=;
if lson>tot then break;
if (lson<tot)and((q[lson].num>q[rson].num)or(q[lson].num=q[rson].num)and(q[lson].deep>q[rson].deep)) then pd:=;
if pd= then son:=lson
else son:=rson;
if (q[x].num<q[son].num)or((q[x].num=q[son].num)and(q[x].deep<q[son].deep)) then break;
swap(q[x],q[son]);
x:=son;
end;
end;
begin
readln(n,k);
for i:= to n do read(a[i]);
if k<> then
while n mod (k-)<> do begin
inc(n); a[n]:=;
end;//如果不是2叉堆需要初始化保证huffman树最后一层的元素到达k个,方便操作
tot:=;
for i:= to n do begin
inc(tot);
q[tot].num:=a[i];
q[tot].deep:=;
up(tot);
end;//建堆
while tot<> do begin
node.num:=;node.deep:=; mxdep:=;//k个元素的和、深度、最大深度
for i:= to k do begin
now:=q[];
swap(q[],q[tot]);
dec(tot);
down();
node.num:=node.num+now.num;
mxdep:=max(mxdep,now.deep);
end;//由于是k进制所以需要取出堆中k个元素
ans:=ans+node.num;//累加
node.deep:=mxdep+;//深度++
inc(tot);
q[tot]:=node;
up(tot);//放回去
end;
writeln(ans);
writeln(mxdep+);//打印
end.

荷马史诗 NOI2015 解析的更多相关文章

  1. 洛谷P2168 荷马史诗 [NOI2015]

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

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

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

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

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

  4. 【NOI2015】荷马史诗[Huffman树+贪心]

    #130. [NOI2015]荷马史诗 统计 描述 提交 自定义测试 追逐影子的人,自己就是影子. ——荷马 Allison 最近迷上了文学.她喜欢在一个慵懒的午后,细细地品上一杯卡布奇诺,静静地阅读 ...

  5. 【BZOJ4198】【NOI2015】荷马史诗(贪心,Huffman树)

    [BZOJ4198][NOI2015]荷马史诗(贪心,Huffman树) 题面 BZOJ 洛谷 题解 合并果子都是不知道多久以前做过的了.现在才知道原来本质就是一棵哈夫曼树啊. 这题我们仔细研究一下题 ...

  6. 【bzoj4198】【Noi2015】荷马史诗

    4198: [Noi2015]荷马史诗 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 2200  Solved: 1169[Submit][Statu ...

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

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

  8. UOJ#130 【NOI2015】荷马史诗 K叉哈夫曼树

    [NOI2015]荷马史诗 链接:http://uoj.ac/problem/130 因为不能有前缀关系,所以单词均为叶子节点,就是K叉哈夫曼树.第一问直接求解,第二问即第二关键字为树的高度. #in ...

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

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

随机推荐

  1. 1.2《想成为黑客,不知道这些命令行可不行》(Learn Enough Command Line to Be Dangerous)——开始第一条命令

    现在开始准备运行我们的第一条命令了,在屏幕上打印'hello'.(字符打印的地方被称为'标准输出',通常指的是屏幕,很少指真的物理打印机设备).这条命令就是echo,这条命令的参数是想要输出的字符串或 ...

  2. 约束布局constraint-layout导入失败的解决方案 - 转

    今天有同事用到了约束布局,但是导入我的工程出现错误 **提示错误: Could not find com.Android.support.constraint:constraint-layout:1. ...

  3. 总结:C# 委托的全面理解

    在说事件之前得先了解委托. 委托,外表看来和C/C++中函数指针没什么区别,但是本质上你才发现他其实就是个类!也就是说理解委托得从 这个两个方面去理解(单从一个方面去理解感觉就怪怪的呵呵!) 理解委托 ...

  4. mapreduce 多种输入

    1.多路径输入 1)FileInputFormat.addInputPath 多次调用加载不同路径 FileInputFormat.addInputPath(job, new Path("h ...

  5. VBA how to crack Excel Password

    来源 更多vba相关 vba教程 VBA cheat sheet 1. VBA how to crack Excel Workbook/Worksheet password To remove the ...

  6. 微信小程序云开发之云函数创建

    云函数 云函数是一段运行在云端的代码,无需管理服务器,在开发工具内编写.一键上传部署即可运行后端代码. 小程序内提供了专门用于云函数调用的 API.开发者可以在云函数内使用 wx-server-sdk ...

  7. [CF1019D]Large Triangle[极角排序+二分]

    题意 给出平面上 \(n\) 个点 \((x_i, y_i)\),问是否存在三个点构成的三角形的面积恰好为 \(S\) ,有的话,输出任意一组解即可. \(n\leq 2000\) 分析 BZOJ37 ...

  8. SSIS 事件的向上传递

    在SSIS中,Package是Task组件的有序组合,具有层次结构,Package处于层次结构的顶层(Root Level),对于父子包结构,父包(Parent Package)通过Execute P ...

  9. 关于Map迭代循环,key和value的顺序问题

    使用Hashtable,keySet()返回的顺序为降序(key降顺序) ---->6, 5, 4, 3, 2, 1使用TreeMap,keySet()返回的顺序为升序(key升顺序) ---- ...

  10. Windows下fabric sdk连接Linux上fabric网络的调试过程

    上个月刚入职一家公司从事区块链研发工作,选型采用Hyperledger Fabric作为开发平台.团队的小组成员全部采用的是在VirtualBox上面安装桌面版的Ubuntu 16.04虚拟机,开发工 ...