sgu-203 Hyperhuffman

题目大意:

给出一个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

sgu-203 Hyperhuffman的相关文章

203. Hyperhuffman

\(O(nlogn)\)可能会超时,最优二叉树有\(O(n)\)的做法,当年合并果子全机房就我最快,哈哈.. 开两个队列,一个存放未合并的节点,一个存放合并之后的子树,每次取最小时只需考虑这两个队列中的最小值即可,可以证明在队列内的元素单调. notice: 输入数据已经排好序了, Characters are given from most rare to most frequent . 1 #include <bits/stdc++.h> 2 #define rep(_i, _j) for

【SGU 390】Tickets (数位DP)

Tickets Description Conductor is quite a boring profession, as all you have to do is just to sell tickets to the passengers. So no wonder that once upon a time in a faraway galaxy one conductor decided to diversify this occupation. Now this conductor

ACM: SGU 101 Domino- 欧拉回路-并查集

sgu 101 - Domino Time Limit:250MS     Memory Limit:4096KB     64bit IO Format:%I64d & %I64u Description Dominoes – game played with small, rectangular blocks of wood or other material, each identified by a number of dots, or pips, on its face. The bl

SGU 116 Index of super-prime 数论+完全背包+输出方案

题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=116 题意好晦涩 给你一个不超过一万的数 问它最少可以用多少个“超级素数”来表示 使“超级素数”之和等于它 如果无法这样表示 输出0 否则 按非降序形式输出方案 数论部分就模板的问题 没什么说的 完全背包方面也很常规 说说[输出方案] 背包九讲的伪码给的是二维dp[]的方法 实际上稍加改动就可以用在一维数组上 用一个rec[]记录dp[]的当前状态是从哪个状态转移而来(即上一个状态) 通过

SGU 乱搞日志

SGU 100 A+B :太神不会 SGU 101 Domino: 题目大意:有N张骨牌,两张骨牌有两面有0到6的数字,能相连当且仅当前后数字相同,问能否有将N张骨牌连接的方案?思路:裸的欧拉回路,注意自环,连通 1 //sgu101 2 #include<iostream> 3 #include<cstdio> 4 #include <math.h> 5 #include<algorithm> 6 #include<string.h> 7 #i

SGU 275 To xor or not to xor (高斯消元)

题目地址:SGU 275 首先,贪心的思想,每一二进制位上要尽量是1,而能不能是1用高斯消元来解决.当该位有一个可以使之为1的变元时,就说明这位可以为1,而且令该变元控制该位,然后向低位消元. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h>

SGU 221.Big Bishops(DP)

题意: 给一个n*n(n<=50)的棋盘,放上k个主教(斜走),求能放置的种类总数. Solution : 同SGU 220,加个高精度就好了. code #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <algorithm> using namespace std; string f[2][250][250], ans;

SGU 193.Chinese Girls&#39; Amusement

/* 实际上就是求一个k,满足k<=n/2,且gcd(n,k)=1 如果n为奇数,k为[n/2] 如果n为偶数,k=n/2-1-(n/2)%2 */ #include <iostream> using namespace std; string s; void div2() { string t; int l = s.size() - 1, tem = s[0] - '0'; if (tem > 1) t += '0' + tem / 2; tem &= 1; for (i

sgu 495 Kids and Prizes

计算出每个人得到礼物的概率,然后加起来即可 1 #include<iostream> 2 #include<string.h> 3 #include<algorithm> 4 #include<stdio.h> 5 using namespace std; 6 double dp[101010]; 7 int main(){ 8 int n,m; 9 while(cin>>n>>m){ 10 dp[1]=1; 11 for(int i

SGU 112 a^b-b^a

JAVA大数.... a^b-b^a Time Limit: 250MS   Memory Limit: 4096KB   64bit IO Format: %I64d & %I64u [Submit]   [Go Back]   [Status] Description You are given natural numbers a and b. Find ab-ba. Input Input contains numbers a and b (1≤a,b≤100). Output Write