#include <iostream>
#include <vector>
#include <queue>
#include <fstream>
using namespace std;
struct Node {
int symbol;
int frequency;
Node* left;
Node* right;
Node(int symbol, int frequency) {
this->symbol = symbol;
this->frequency = frequency;
left = nullptr;
right = nullptr;
}
};
struct Compare {
bool operator()(Node* a, Node* b) {
return a->frequency > b->frequency;
}
};
void generateHuffmanCodes(Node* root, string codePrefix, vector<string>& huffmanCodes) {
if (root->left == nullptr && root->right == nullptr) {
huffmanCodes[root->symbol] = codePrefix;
return;
}
generateHuffmanCodes(root->left, codePrefix + "0", huffmanCodes);
generateHuffmanCodes(root->right, codePrefix + "1", huffmanCodes);
}
int main() {
ifstream inputFile("huffman.in");
ofstream outputFile("huffman.out");
int n;
inputFile >> n;
vector<int> frequencies(n);
for (int i = 0; i < n; i++) {
inputFile >> frequencies[i];
}
priority_queue<Node*, vector<Node*>, Compare> pq;
for (int i = 0; i < n; i++) {
Node* node = new Node(i, frequencies[i]);
pq.push(node);
}
while (pq.size() > 1) {
Node* leftChild = pq.top();
pq.pop();
Node* rightChild = pq.top();
pq.pop();
int totalFrequency = leftChild->frequency + rightChild->frequency;
Node* internalNode = new Node(-1, totalFrequency);
internalNode->left = leftChild;
internalNode->right = rightChild;
pq.push(internalNode);
}
Node* root = pq.top();
vector<string> huffmanCodes(n);
generateHuffmanCodes(root, "", huffmanCodes);
long long minLength = 0;
for (int i = 0; i < n; i++) {
minLength += frequencies[i] * huffmanCodes[i].length();
}
outputFile << minLength << "\n";
for (int i = 0; i < n; i++) {
outputFile << huffmanCodes[i].length() << " " << stoll(huffmanCodes[i], nullptr, 2) << "\n";
}
inputFile.close();
outputFile.close();
return 0;
}