当前位置:   article > 正文

【CodeForces】700 D. Huffman Coding on Segment 哈夫曼树+莫队+分块

codeforces huffman

【题目】D. Huffman Coding on Segment

【题意】给定n个数字,m次询问区间[l,r]的数字的哈夫曼编码总长。1<=n,m,ai<=10^5。

【算法】哈夫曼树+莫队+分块

【哈夫曼树】哈夫曼树又称最优构造树,n个数字的哈夫曼树是含有n个给定权值叶子的点权路径和最小的二叉树。

点权路径和(WPL)可以表示为每个点的深度*权值

构造方法:每次取点权最小的两个根节点作为左右子树(左小右大)组成新根节(点权为左右之和),多次操作直到只剩一棵树。(类似合并果子)

哈夫曼树的WPL是所有节点的权值和-数字和(也是非叶子节点的权值和,或是所有非根节点的权值和)。

哈夫曼编码:从根出发左0右1,走到每个字符的二进制就是它的编码。

Huffman Code是电文总长最短的二进制编码方式,将n个字符的出现频率作为点权构造哈夫曼树得到的就是对应的哈夫曼编码。

n个数字的哈夫曼编码长度和就是WPL。

【题解】对于一个区间,令f[x]表示数字x的出现次数,令g[x]表示出现次数为x的数字个数,用莫队维护。

每次区间询问,考虑朴素做法是将出现次数作为点权,构造哈夫曼树,但这样太慢了。令S=sqrt(n)。

对于出现次数>S的数字,一共只有不超过S个,按朴素做法构造哈夫曼树求解即可,复杂度O(S log S)。

对于出现次数<S的数字,考虑到点权很小,可以用一个桶记录,就可以批量做了,复杂度O(S),点权一旦超过S就进入上一过程。

总复杂度O(n√n)。

 

转载于:https://www.cnblogs.com/onioncyc/p/8855864.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/71298
推荐阅读
相关标签
  

闽ICP备14008679号