Cod sursa(job #3301179)

Utilizator MihaiZ777MihaiZ MihaiZ777 Data 22 iunie 2025 16:27:18
Problema Coduri Huffman Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.11 kb
#include <algorithm>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <vector>
#include <fstream>
#include <cstring>
using namespace std;

#define fast_io ios::sync_with_stdio(0); cin.tie(0); do{}while(0)
typedef long long ll;

ifstream fin("huffman.in");
ofstream fout("huffman.out");

const int MAXN = 1e6 + 5;

struct Entry {
	long long id;
	long long frv;

	bool operator <(const Entry& other) const {
		return frv > other.frv;
	}
};

long long n;
long long frv[MAXN];
queue<Entry> realKeys;
queue<Entry> virtualKeys;
vector<int> graph[MAXN * 2];
pair<long long, long long> ans[MAXN];
long long id = 0;

void ReadData() {
	fin >> n;
	for (int i = 0; i < n; i++) {
		fin >> frv[i];
		realKeys.push({id++, frv[i]});
	}
}

Entry ExtractMinKey() {
	Entry entry;
	if (virtualKeys.empty()) {
		entry = realKeys.front();
		realKeys.pop();
	} else if (realKeys.empty()) {
		entry = virtualKeys.front();
		virtualKeys.pop();
	} else if (realKeys.front().frv < virtualKeys.front().frv) {
		entry = realKeys.front();
		realKeys.pop();
	} else {
		entry = virtualKeys.front();
		virtualKeys.pop();
	}
	return entry;
}

int BuildHuffman() {
	while (realKeys.size() + virtualKeys.size() > 1) {
		Entry a = ExtractMinKey();
		Entry b = ExtractMinKey();

		graph[id].push_back(a.id);
		graph[id].push_back(b.id);
		virtualKeys.push({id, a.frv + b.frv});
		id++;
	}
	return virtualKeys.front().id;
}

void BuildAnswer(long long node, long long height, long long value) {
	if (node < n) {
		ans[node] = {height, value};
		return;
	}
	BuildAnswer(graph[node][0], height + 1, value << 1);
	BuildAnswer(graph[node][1], height + 1, (value << 1) | 1);
}

void Solve() {
	long long root = BuildHuffman();
	BuildAnswer(graph[root][0], 1, 0);
	BuildAnswer(graph[root][1], 1, 1);

	long long sum = 0;
	for (int i = 0; i < n; i++) {
		sum += ans[i].first * frv[i];
	}
	fout << sum << '\n';
	for (int i = 0; i < n; i++) {
		fout << ans[i].first << ' ' << ans[i].second << '\n';
	}
}

int main() {
		ReadData();
		Solve();
		return 0;
}