Cod sursa(job #2620615)

Utilizator radustn92Radu Stancu radustn92 Data 29 mai 2020 12:20:48
Problema Coduri Huffman Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.86 kb
#include <cstdio>
#include <iostream>
#include <queue>
using namespace std;
const int NMAX = 1000505;

struct node {
	long long weight;

	int leftChild, rightChild;

	node() {}

	node(long long _weight) : node(_weight, -1, -1) { }

	node(long long _weight, int _leftChild, int _rightChild) {
		weight = _weight;
		leftChild = _leftChild;
		rightChild = _rightChild;
	}
};

int N, A[NMAX];
node nodes[2 * NMAX];
// first N are leaves, next N - 1 are internal nodes
int nextLeaf, nextInternalNode, totalNodes;
pair<int, long long> result[NMAX];
long long totalLength;

int extractMinimum() {
	int resultIdx = -1;
	if (nextLeaf == N + 1 || (nextInternalNode <= totalNodes && nodes[nextLeaf].weight > nodes[nextInternalNode].weight)) {
		return nextInternalNode++;
	}
	return nextLeaf++;
}

void dfs(int currNodeIdx, int depth, long long currPrefix) {
	if (currNodeIdx == -1) {
		return;
	} else if (currNodeIdx <= N) {
		result[currNodeIdx] = {depth, currPrefix};
		totalLength += nodes[currNodeIdx].weight * depth;
		return;
	}

	dfs(nodes[currNodeIdx].leftChild, depth + 1, currPrefix << 1);
	dfs(nodes[currNodeIdx].rightChild, depth + 1, (currPrefix << 1) + 1);
}

int main() {
	freopen("huffman.in", "r", stdin);
	freopen("huffman.out", "w", stdout);

	cin.tie(NULL);
	ios_base::sync_with_stdio(false);

	cin >> N;
	for (int i = 1; i <= N; i++) {
		cin >> A[i];
		nodes[i] = node(A[i]);
	}

	nextLeaf = 1;
	totalNodes = N;
	nextInternalNode = N + 1;
	while (N + 1 - nextLeaf + (totalNodes + 1) - nextInternalNode > 1) {
		int firstMin = extractMinimum();
		int secondMin = extractMinimum();
		int newWeight = nodes[firstMin].weight + nodes[secondMin].weight;

		node newNode{newWeight, firstMin, secondMin};
		nodes[++totalNodes] = newNode;
	}

	dfs(totalNodes, 0, 0);
	cout << totalLength << "\n";
	for (int i = 1; i <= N; i++) {
		cout << result[i].first << " " << result[i].second << "\n";
	}
	return 0;
}