【BZOJ 4198】[Noi2015]荷马史诗 哈夫曼编码
2024-08-31 04:16:03
合并果子加强版.......
哈夫曼树是一种特别的贪心算法,它的作用是使若干个点合并成一棵树,每次合并新建一个节点连接两个合并根并形成一个新的根,使叶子节点的权值乘上其到根的路径长的和最短(等价于每次合并的代价是合并根的权值和,求最小代价)。实现过程就是每次合并权值最小的两个节点,具体一下就是建个森林,每次取最小的两个然后权值加和再放入,重复。
他的实际应用就是哈夫曼编码,拓展就是k叉(本题),对于k叉也就是k进制,如果叶子节点不是1+(k-1)*x的形式,那么就加权值为0的点使他变成此种形式,不能到最后一次再加,那样做不是最优树。
关于哈夫曼编码有静态(本题)和动态,并不会动态......
具体实现的话,工程里是循环找最小,oi里是优先队列。
#include <cstdio>
#include <cstring>
#include <algorithm>
#define HoN Heap::
#define make(a,b) ((Heap::V){(a),(b)})
typedef long long LL;
const int N=;
namespace Heap{
struct V{
LL val;int deep;
inline friend bool operator <(V a,V b);
}k[N];
int len;
inline bool operator <(V a,V b){
return a.val<b.val||(a.val==b.val&&a.deep<b.deep);
}
inline bool empty(){return len==;}
inline V top(){return k[];}
inline int size(){return len;}
inline void pop(){
k[]=k[len--];register int now=;
while(now<=(len>>)){
int next=now<<;
if(next<len&&k[next|]<k[next])next|=;
if(k[now]<k[next])return;
std::swap(k[now],k[next]),now=next;
}
}
inline void push(V key){
k[++len]=key;register int now=len;
while(now!=&&k[now]<k[now>>])
std::swap(k[now],k[now>>]),now>>=;
}
}
int n,k;
LL ans;
int main(){
scanf("%d%d",&n,&k);LL x;
for(int i=;i<=n;++i)
scanf("%lld",&x),HoN push(make(x,));
if(k!=&&n%(k-)!=){
if(n%(k-)==)HoN push(make(,)),++n;
else{
for(int i=;i<=k-(n%(k-));++i)
HoN push(make(,));
n+=n%(k-);
}
}
int m=k==?n-:n/(k-);
int max;HoN V use;
while(m--){
x=,max=;
for(int i=;i<=k;++i)
use=HoN top(),HoN pop(),x+=use.val,max=std::max(max,use.deep);
ans+=x,HoN push(make(x,max+));
}
printf("%lld\n%d",ans,HoN top().deep-);
return ;
}
最新文章
- cxf设置代理访问webservice接口
- OpenGL 多视图与截屏
- Redis系列-冷知识
- Linux sed 批量替换多个文件中的字符串
- java serializable深入了解
- bzoj 3037 贪心
- centOS 6.4 vsftpd 安装配置
- Ext入门的第一个程序(1)
- zxing源码分析——QR码部分
- Java中的位运算符、移位运算
- HDU 1272 小希的迷宫(乱搞||并查集)
- MediaPlayer的错误列表速查(android)
- linux之scp
- java 整型数组基本排序,冒泡,快速选择,插入,归并
- DNS:域名系统
- Mybatis动态SQL单一基础类型参数用if标签
- Qt之QDomDocument操作xml文件-模拟ini文件存储
- vue定义全局组件
- #WEB安全基础 : HTTP协议 | 0x11 HTTP的分块传输模块
- Docker在Windows上运行NetCore系列(一)使用命令控制台运行.NetCore控制台应用
热门文章
- scrapy框架爬取笔趣阁完整版
- Java学习笔记十三:Java中的类和对象
- Java学习笔记五:Java中常用的运算符
- 017---Django的中间件解决跨域
- Git 克隆指定分支代码
- R语言学习笔记(十二):零碎知识点(31-35)
- R语言学习笔记(四):apply,sapply,lapply,tapply,vapply以及mapply的用法
- 封装一个ExcelHelper,方便将Excel直接转成Datatable对象
- 在编程的时候,NotePad++ 中闪烁的光标突然有竖着闪烁的编程蓝色下划线闪烁的--小技巧告诉你-费元星
- 通过repcached实现memcached主从复制