#include <fstream>
#include <queue>
struct Node
{
long long nr;
bool c;
int place;
Node *left, *right;
Node() : nr(), c(false), left(NULL), right(NULL) {}
Node(long long a, int b) : nr(a), c(true), place(b), left(NULL), right() {}
Node(Node *a, Node *b) : nr(a->nr + b-> nr), c(false), left(a), right(b) {}
};
struct Pair
{
long long a, b;
Pair() : a(), b() {}
Pair(long long c, long long d) : a(c), b(d) {}
};
Node* extract(std::queue<Node*> &A, std::queue<Node*> &B);
void dfs(Node *A, long long &nr, Pair *myP, long long a, long long b);
int main()
{
std::ifstream in("huffman.in");
std::ofstream out("huffman.out");
int nV;
long long nr;
std::queue<Node*> myQ1, myQ2;
in >> nV;
for(int i = 0; i < nV; i++)
in >> nr, myQ1.push(new Node(nr, i));
Node *a = NULL, *b = NULL;
while(true)
{
a = extract(myQ1, myQ2);
b = extract(myQ1, myQ2);
if(b == NULL) break;
else myQ2.push(new Node(a, b));
}
nr = 0;
Pair *myP = new Pair[nV];
dfs(a, nr, myP, 0, 0);
out << nr << '\n';
for(unsigned i = 0; i < nV; i++)
out << myP[i].a << ' ' << myP[i].b << '\n';
return 0;
}
Node* extract(std::queue<Node*> &A, std::queue<Node*> &B)
{
Node *c = NULL;
if(A.empty() && B.empty())
return c;
else if(A.empty() && !B.empty())
{
c = B.front();
B.pop();
}
else if(!A.empty() && B.empty())
{
c = A.front();
A.pop();
}
else
{
if(A.front()->nr < B.front()->nr)
{
c = A.front();
A.pop();
}
else
{
c = B.front();
B.pop();
}
}
return c;
}
void dfs(Node *A, long long &nr, Pair *myP, long long a, long long b)
{
if(!A->c)
{
nr += A->nr;
dfs(A->left, nr, myP, a + 1, b * 2);
dfs(A->right, nr, myP, a + 1, b * 2 + 1);
}
else myP[A->place] = Pair(a, b);
return;
}