Cod sursa(job #407541)

Utilizator laserbeamBalan Catalin laserbeam Data 2 martie 2010 13:43:54
Problema Coduri Huffman Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.49 kb
// Catalin Balan
// Tue Mar  2 12:08:04 EET 2010
// Infoarena - Coduri Huffman - var cu heap ( n log n )

#include <cstdio>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <utility>

using namespace std;

#define	NMAX 1000004
#define CHUNK 8192

#define FIN "huffman.in"
#define FOUT "huffman.out"

char g_buf[CHUNK];
int g_p=CHUNK-1;

inline long long get(FILE *f)
{

	long long x = 0;
	while (g_buf[g_p] < '0' || g_buf[g_p] > '9')
		if (++g_p == CHUNK) fread(g_buf,1,CHUNK,f), g_p=0;

	while (g_buf[g_p] >= '0' && g_buf[g_p] <= '9')
	{
		x = x*10 + g_buf[g_p]-'0';
		if (++g_p == CHUNK) fread(g_buf,1,CHUNK,f), g_p=0;
	}
	return x;
}

struct node
{
	long long val;
	int fiu0, fiu1;
} noduri[ 2*NMAX ];

long long cod[NMAX], totlen;
int lung[NMAX];
//vector< pair< long long, int > > heap;
int n;

void df( int p, int depth, long long x )
{
	
	//printf("%d - %lld %d %d\n", p, noduri[p].val, noduri[p].fiu0, noduri[p].fiu1);

	if ( noduri[p].fiu0 )
	{
		df( noduri[p].fiu0, depth+1, x<<1     );
		df( noduri[p].fiu1, depth+1, (x<<1)+1 );
		return;
	}
	lung[p] = depth;
	cod[p] = x;
	totlen += depth * noduri[p].val;

}


void solve()
{
	int i = n;
	int q1 = 1, q2 = n+1, q;
	long long aux;
//	make_heap( heap.begin(), heap.end());

	while ( q1 < n || q2 < i)
	{
		++i;
		noduri[i].val = 0;

		if ( q1 <= n && ( q2 >= i || noduri[q1].val <= noduri[q2].val ) ) 	{aux = noduri[q1].val; q = q1; q1++;}
		else 																{aux = noduri[q2].val; q = q2; q2++;}

		noduri[i].val += aux;
		noduri[i].fiu0 = q;

		if ( q1 <= n && ( q2 >= i || noduri[q1].val <= noduri[q2].val ) ) 	{aux = noduri[q1].val; q = q1; q1++;}
		else 																{aux = noduri[q2].val; q = q2; q2++;}

		noduri[i].val += aux;
		noduri[i].fiu1 = q;

/*		aux = heap.front();
		noduri[i].val -= aux.first;
		noduri[i].fiu0 = aux.second;
		pop_heap( heap.begin(), heap.end() );
		heap.pop_back();

		aux = heap.front();
		noduri[i].val -= aux.first;
		noduri[i].fiu1 = aux.second;
		pop_heap( heap.begin(), heap.end() );
		heap.pop_back();

		heap.push_back( make_pair( -noduri[i].val, i) );
*/
	}

//	aux = heap.front();
	df( i, 0, 0 );

}


int main(int argv, char ** argc)
{
	freopen(FIN, "r", stdin);
	freopen(FOUT, "w", stdout);

	n = get(stdin);
	for (int i = 1; i <= n; ++i)
	{
		noduri[i].val = get(stdin);
		noduri[i].fiu0 = noduri[i].fiu1 = 0;
//		heap.push_back( make_pair( -noduri[i].val, i ) );
	}

	solve();

	printf( "%lld\n", totlen );
	for (int i = 1; i <= n; ++i)
	{
		printf( "%d %lld\n", lung[i], cod[i] );
	}
	
	return EXIT_SUCCESS;
}