Cod sursa(job #1979577)

Utilizator mouse_wirelessMouse Wireless mouse_wireless Data 10 mai 2017 21:16:39
Problema Coduri Huffman Scor 65
Compilator cpp Status done
Runda Arhiva educationala Marime 2 kb
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
#include <cassert>
#include <cstring>
#include <climits>
using namespace std;
typedef long long LL;

#ifdef INFOARENA
#define ProblemName "huffman"
#endif

#define MCONCAT(A, B) A B
#ifdef ProblemName
#define InFile MCONCAT(ProblemName, ".in")
#define OuFile MCONCAT(ProblemName, ".out")
#else
#define InFile "fis.in"
#define OuFile "fis.out"
#endif

#define MAXN 1000010

struct nod {
	LL cost;
	nod *parent;
	int bit;
} v[MAXN], others[MAXN << 1];

int N;

pair<int, int> repr[MAXN];

void setRepr(int i) {
	nod *p = &v[i];
	while (p->parent != NULL) {
		++repr[i].first;
		repr[i].second = (repr[i].second << 1) | p->bit;
		p = p->parent;
	}
	int o = 0;
	for (int j = 0; j < repr[i].first; ++j) {
		o = (o << 1) | (repr[i].second & 1);
		repr[i].second >>= 1;
	}
	repr[i].second = o;
}

int main() {
	assert(freopen(InFile, "r", stdin));
	assert(freopen(OuFile, "w", stdout));
	scanf("%d", &N);
	for (int i = 0; i < N; ++i)
		scanf("%lld", &v[i].cost);
	int i0 = 0, i1 = 0, qe = 0;
	while (i0 < N) {
		nod *p0;
		if (i1 < qe && others[i1].cost < v[i0].cost) {
			p0 = &others[i1];
			i1++;
		}
		else {
			p0 = &v[i0];
			i0++;
		}
		nod *p1;
		if (i0 >= N || i1 < qe && others[i1].cost < v[i0].cost) {
			p1 = &others[i1];
			i1++;
		}
		else {
			p1 = &v[i0];
			i0++;
		}
		others[qe].cost = p0->cost + p1->cost;
		p0->parent = &others[qe]; p0->bit = 0;
		p1->parent = &others[qe]; p0->bit = 1;
		++qe;
	}
	while (i1 < qe - 1) {
		nod *p0 = &others[i1];
		nod *p1 = &others[i1 + 1];
		others[qe].cost = p0->cost + p1->cost;
		p0->parent = &others[qe]; p0->bit = 0;
		p1->parent = &others[qe]; p0->bit = 1;
		++qe;
		i1 += 2;
	}
	for (int i = 0; i < N; ++i)
		setRepr(i);
	LL ans = 0;
	for (int i = 0; i < N; ++i)
		ans += v[i].cost * repr[i].first;
	printf("%lld\n", ans);
	for (int i = 0; i < N; ++i)
		printf("%d %d\n", repr[i].first, repr[i].second);
	return 0;
}