题目大意:
给出一个n,表示一篇文章中的不同单词的个数为n,然后接下来给出n个整数,表示各个单词出现的频率,要你求对这篇文章的所有单词huffman转码后的文章的长度。
解题思路:
首先看到这道题目准备直接去构造huffman tree,但是后来懒得写(其实是我太渣),然后脑补了一下发现了什么:
这道题目实际上不需要建树,因为只要求huffman tree 的权值(就是每个叶子节点的权值乘以对应深度)。所以我们想到了用另一个好东西——小根堆!!!!!
但是如何用小根堆做呢?我们观察一下huffman tree 的权值,会发现也等于每个节点的权值和,根据这个道理,我们可以当小根堆中的元素个数大于1时,将最小的两个合并成一个,权值相加,然后将这个点重新插入堆中,ans+=v[i]+v[j](两个合并的权值),然后当只剩下一个元素的时候就跳出循环输出ans就行了
AC代码:
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <iostream> #include <algorithm> using namespace std; long long a[500010]={0}; long long ans=0; int n; void tz(int k) { long long p=(long long)2e19,q=(long long)2e19; if(k*2<=n) p=a[k*2]; if(k*2+1<=n) q=a[k*2+1]; if(p<=q && p<=a[k]) { swap(a[k],a[k*2]); tz(k*2); } else if(q<=p && q<=a[k]) { swap(a[k*2+1],a[k]); tz(k*2+1); } return; } int main() { cin>>n; for(int i=1;i<=n;i++) scanf("%I64d",&a[i]); sort(a+1,a+n+1); for(;n>1;) { long long x1=a[1]; swap(a[1],a[n]); n--; tz(1); long long x2=a[1]; ans+=x1+x2; a[1]=x1+x2; tz(1); } printf("%I64d\n",ans); return 0; }
时间: 2024-10-21 17:53:50