题目大意:
给出一个n,表示一篇文章中的不同单词的个数为n,然后接下来给出n个整数,表示各个单词出现的频率,要你求对这篇文章的所有单词huffman转码后的文章的长度。
解题思路:
首先看到这道题目准备直接去构造huffman tree,但是后来懒得写(其实是我太渣),然后脑补了一下发现了什么:
这道题目实际上不需要建树,因为只要求huffman tree 的权值(就是每个叶子节点的权值乘以对应深度)。所以我们想到了用另一个好东西——小根堆!!!!!
给出一个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;
}