Cod sursa(job #372978)

Utilizator MariusMarius Stroe Marius Data 12 decembrie 2009 12:47:32
Problema Coduri Huffman Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.17 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <cassert>
using namespace std;

const char iname[] = "huffman.in";
const char oname[] = "huffman.out";

typedef long long i64;

struct huffman_node {
	i64 fr;
	int index, l_index, r_index;

	void set(i64 f, int i, int l, int r) {
		fr = f;
		index = i, l_index = l, r_index = r;
	}
	void setFr(i64 f) {
		fr = f;
	}
};

bool operator < (const huffman_node& a, const huffman_node& b) {
	return a.fr < b.fr;
}

bool operator <= (const huffman_node& a, const huffman_node& b) {
	return a.fr <= b.fr;
}

vector <huffman_node> Q;	vector <int> lg;	vector <i64> b;

void walk(int i, int length, i64 code) {
	if (Q[i].l_index + Q[i].r_index == -2) {
		assert(length <= 64);
		assert(0 <= code && code <= (1LL << 60));
		assert(Q[i].index < (int) b.size());
		lg[Q[i].index] = length;
		b[Q[i].index] = code;
	}
	if (Q[i].l_index >= 0)
		walk(Q[i].l_index, length + 1, code * 2);
	if (Q[i].r_index >= 0)
		walk(Q[i].r_index, length + 1, code * 2 + 1);
}

int main(void) {
	int n;

	ifstream in(iname);
	assert(in >> n);
	Q.resize(2 * n);
	for (int i = 0; i < n; ++ i) {
		int fr;
		assert(in >> fr);
		assert(1 <= fr && fr <= 100000000);
		Q[i].set(fr, i, -1, -1);
		if (i > 0)
			assert(Q[i - 1] <= Q[i]);
	}
	for (int i = 0, j = n, cnt_n = n; cnt_n < 2 * n - 1; ) {
		huffman_node h1, h2;
		h1.setFr(-1), h2.setFr(-1);

		for (int k = i; k < min(i + 2, n); ++ k) {
			if (Q[k] < h1 || h1.fr == -1)
				h2 = h1, h1 = Q[k];
			else if (Q[k] < h2 || h2.fr == -1)
				h2 = Q[k];
		}
		for (int k = j; k < min(j + 2, cnt_n); ++ k) {
			if (Q[k] < h1 || h1.fr == -1)
				h2 = h1, h1 = Q[k];
			else if (Q[k] < h2 || h2.fr == -1)
				h2 = Q[k];
		}
		Q[cnt_n].set(h1.fr + h2.fr, cnt_n, h1.index, h2.index);
		cnt_n ++;
		(h1.index < n) ? ++ i : ++ j;
		(h2.index < n) ? ++ i : ++ j;
	}
	lg.resize(n);
	b.resize(n);
	walk(2 * n - 2, 0, 0);

	ofstream out(oname);
	i64 res = 0;
	for (int i = n; i < 2 * n - 1; ++ i)
		res += Q[i].fr;
	out << res << "\n";
	for (int i = 0; i < n; ++ i)
		out << lg[i] << " " << b[i] << "\n";
	out.close();
	return 0;
}