Pagini recente » Cod sursa (job #839019) | Cod sursa (job #2955151) | Cod sursa (job #1745942) | Cod sursa (job #1321941) | Cod sursa (job #374134)
Cod sursa(job #374134)
#include<stdio.h>
#define infile "huffman.in"
#define outfile "huffman.out"
#define nmax (1000*1001)
#define bmax 63
struct nod
{
long long val; //valoarea din acest nod
long long nr; //numarul ce se formeaza in parcurgerea de la radacina pana la el
int lg; //lungimea de la radacina pana la el
int t; //tatal nodului
char b; //tipul bitului (adica daca e de dreapta sau de stanga "=))'" )
int st,dr; //adresa catre cei 2 fii
} n[2*nmax]; //informatiile arborelui ce se formeaza
long long b[bmax]; //b[i]=2^i
int m; //numarul de noduri
int rad; //radacina arborelui
long long lg; //lungimea noului text
inline void unit(int i, int j, int k)
{ //uneste nodurile i si j in nodul k
n[k].val=n[i].val+n[j].val;
n[k].st=i; n[k].dr=j;
}
inline int min(int *st1, int *dr1, int *st2)
{
if(*st1<=*dr1 && n[*st1].val<=n[*st2].val) { *st1+=1; return *st1-1; }
*st2+=1; return *st2-1;
}
void read()
{
int i;
scanf("%d\n",&m);
for(i=1;i<=m;i++)
scanf("%lld\n",&n[i].val);
}
void init()
{
int st1=3,dr1=m; //capetele primei cozi
int st2=m+1,dr2=m+1; //capetele celeilalte cozi
int i,j;
//initializam coada 2
unit(1,2,st2);
//transformam padurea intr-un arbore huffman
while(st1<=dr1 || st2<dr2)
unit(min(&st1,&dr1,&st2),min(&st1,&dr1,&st2),++dr2);
//salvam radacina arborelui
rad=dr2;
//construim vectorul b
for(b[0]=i=1;i<bmax;i++)
b[i]=2*b[i-1];
}
void dfs(int rad, int lg)
{
n[rad].lg=lg;
if(n[rad].st) n[n[rad].st].t=rad,dfs(n[rad].st,lg+1);
if(n[rad].dr) n[n[rad].dr].t=rad,n[n[rad].dr].b=1,dfs(n[rad].dr,lg+1);
}
void solve()
{
int i,j,k;
//calculam lungimea totala a textului
for(i=1;i<=m;i++)
lg+=n[i].val*n[i].lg;
//calculam pentru toate nodurile terminale, numarul ce-l formeaza pana la radacina
for(i=1;i<=m;i++)
for(k=0,j=i;j;k++,j=n[j].t)
if(n[j].b)
n[i].nr+=b[k];
}
void write()
{
int i;
//lungimea noului text
printf("%lld\n",lg);
//afisem informatiile fiecarui caracter
for(i=1;i<=m;i++)
printf("%d %lld\n",n[i].lg,n[i].nr);
}
int main()
{
freopen(infile,"r",stdin);
freopen(outfile,"w",stdout);
read();
init();
dfs(rad,0);
solve();
write();
fclose(stdin);
fclose(stdout);
return 0;
}