#include <cstdint>
#include <fstream>
#include <queue>
#include <vector>
using namespace std;
struct Code
{
int length;
int64_t num;
};
struct Node
{
int id = -1;
int cost = 0;
int symbol = -1;
int zero = -1;
int one = -1;
Node() {}
Node(int id, int cost, int symbol = -1)
: id(id), cost(cost), symbol(symbol) {}
};
using Tree = vector<Node>;
int PopCheapest(queue<int> &q1, queue<int> &q2, const Tree &tree)
{
int res = -1;
if (q1.empty() || (!q2.empty() && tree[q2.front()].cost < tree[q1.front()].cost)) {
res = q2.front();
q2.pop();
} else {
res = q1.front();
q1.pop();
}
return res;
}
void Dfs(const Tree &tree, int node, int length, int64_t num, vector<Code> &codes, int64_t &cost)
{
if (tree[node].symbol >= 0) {
codes[tree[node].symbol] = (Code){.length = length, .num = num};
cost += 1LL * length * tree[node].cost;
}
if (tree[node].zero >= 0) {
Dfs(tree, tree[node].zero, length + 1, (num << 1), codes, cost);
}
if (tree[node].one >= 0) {
Dfs(tree, tree[node].one, length + 1, (num << 1) + 1, codes, cost);
}
}
vector<Code> ExtractCodes(const Tree &tree, int root, int symbols, int64_t &cost)
{
vector<Code> codes(symbols);
Dfs(tree, root, 0, 0, codes, cost);
return codes;
}
vector<Code> FindCodes(const vector<int> &count, int64_t &cost)
{
queue<int> q1, q2;
Tree tree(2 * count.size() - 1);
for (size_t i = 0; i < count.size(); i += 1) {
tree[i] = Node(i, count[i], i);
q1.push(i);
}
int next_index = count.size();
while (q1.size() + q2.size() > 1) {
auto a = PopCheapest(q1, q2, tree);
auto b = PopCheapest(q1, q2, tree);
auto cost = tree[a].cost + tree[b].cost;
tree[next_index] = Node(tree.size(), cost);
tree[next_index].zero = a;
tree[next_index].one = b;
q2.push(next_index);
next_index += 1;
}
return ExtractCodes(tree, q2.front(), count.size(), cost);
}
int main()
{
ifstream fin("huffman.in");
ofstream fout("huffman.out");
int symbols;
fin >> symbols;
vector<int> count(symbols);
for (auto &c : count) {
fin >> c;
}
int64_t length = 0;
auto codes = FindCodes(count, length);
fout << length << "\n";
for (const auto &code : codes) {
fout << code.length << " " << code.num << "\n";
}
return 0;
}