#include <bits/stdc++.h>
using namespace std;
using int64 = long long;
ifstream fin("huffman.in");
ofstream fout("huffman.out");
struct node {
node *st, *dr;
int ind;
};
const int NMAX = 1e6 + 6;
int N, lg[NMAX], idx;
int64 sol[NMAX], wt[NMAX << 1], ans;
queue<node*> Q1, Q2;
void read_input() {
fin >> N;
for (int i = 1; i <= N; ++i) {
fin >> wt[i];
node *p = new node;
p->ind = i;
p->st = p->dr = nullptr;
Q1.emplace(p);
}
}
node* take_best() {
node *ans;
if (Q2.empty()) {
ans = Q1.front();
Q1.pop();
} else {
if (Q1.empty()) {
ans = Q2.front();
Q2.pop();
} else {
int64 wt1 = wt[Q1.front()->ind], wt2 = wt[Q2.front()->ind];
if (wt1 < wt2) {
ans = Q1.front();
Q1.pop();
} else {
ans = Q2.front();
Q2.pop();
}
}
}
return ans;
}
void dfs(node *u, int64 mask, int depth) {
if (u->ind <= N) {
sol[u->ind] = mask;
lg[u->ind] = depth;
ans += wt[u->ind] * depth;
return;
}
if (u->st)
dfs(u->st, mask << 1LL, depth + 1);
if (u->dr)
dfs(u->dr, mask << 1LL | 1LL, depth + 1);
}
void solve() {
idx = N;
while (Q1.size() + Q2.size() > 1) {
node *lSon = take_best(), *rSon = take_best();
node *parent = new node;
wt[++idx] = wt[lSon->ind] + wt[rSon->ind];
parent->ind = idx;
parent->st = lSon;
parent->dr = rSon;
Q2.emplace(parent);
}
node *root = Q2.front();
dfs(root, 0, 0);
fout << ans << '\n';
for (int i = 1; i <= N; ++i)
fout << lg[i] << ' ' << sol[i] << '\n';
}
void close_files() {
fin.close();
fout.close();
}
int main() {
read_input();
solve();
close_files();
return 0;
}