#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e5;
typedef struct hfmnode{
int parent;
int lchild;
int rchild;
int weight;
}hfmnode;
typedef struct{
char cd[N];
int start;
}hfmcode;
void select(hfmnode hfm[],int &t1,int &t2,int n){
hfm[0].weight=100;
for(int i=1;i<=n;i++){
if(hfm[i].parent==0)
{
if(hfm[i].weight<hfm[t1].weight)
t1=i;
}
}
for(int i=1;i<=n;i++){
if(hfm[i].parent==0&&i!=t1)
{
if(hfm[i].weight<hfm[t2].weight)
t2=i;
}
}
}
void hfm_create(int w[],hfmnode hfm[],int n){
for(int i=1;i<=n;i++){
hfm[i]={0,0,0,w[i]};
}
int m=2*n-1;
for(int i=n+1;i<=m;i++) hfm[i]={0,0,0,0};//初始化
for(int i=n+1;i<=m;i++){
int tr1=0,tr2=0;
int &t1=tr1;
int &t2=tr2;
select(hfm,t1,t2,i-1);
hfm[i].weight=hfm[t1].weight+hfm[t2].weight;
hfm[i].lchild=t1;
hfm[i].rchild=t2;
hfm[t1].parent=i;
hfm[t2].parent=i;
}
}
void hfm_encode(hfmnode hfm[],hfmcode code[],int n){
char temp[n+1];
for(int i=1;i<=n;i++){
int start=n;//应该倒着搞的
int child=i;
int parent=hfm[i].parent;
while(parent!=0){
if(hfm[parent].lchild==child) temp[start--]='0';
else temp[start--]='1';
child=parent;
parent=hfm[child].parent;
}
for(int j=n;j>start;j--){
code[i].cd[j]=temp[j];
}
code[i].start=start+1;
}
}
void hfm_decode(hfmnode hfm[],hfmcode code[],int k,int n){
int child=2*n-1;//从根开始
int i=code[k].start;
while(i<=n){
if(code[k].cd[i++]=='0') child=hfm[child].lchild;
else child=hfm[child].rchild;
// cout<<child<<' '<<endl;
}
cout<<hfm[child].weight;
}
int main(){
hfmnode hfm[N];
int n;
cin>>n;
int w[N];
for(int i=1;i<=n;i++) cin>>w[i];
hfm_create(w,hfm,n);
for(int i=1;i<=2*n-1;i++){
cout<<hfm[i].weight<<' '<<hfm[i].parent<<' '<<hfm[i].lchild<<' '
<<hfm[i].rchild<<endl;
}
// 25
// 10 15
// 5 5 7 8
// 2 3
hfmcode code[n+1];//下标从1开始
hfm_encode(hfm,code,n);
for(int i=1;i<=n;i++){//这里发现需要倒序输入
for(int j=code[i].start;j<=n;j++){
cout<<code[i].cd[j];
}
cout<<endl;
}
//至于哈夫曼译码,我的理解就是给一棵哈夫曼树,然后给一个编码序列,你输出叶子
hfm_decode(hfm,code,5,5);//输出二号顶点权值
}