Pagini recente » Cod sursa (job #53468) | Cod sursa (job #1824466) | Cod sursa (job #1215425) | Cod sursa (job #2036085) | Cod sursa (job #2792236)
#include <bits/stdc++.h>
using namespace std;
ifstream f("huffman.in");
ofstream g("huffman.out");
int n,m,nr;
long long suma;
struct nod
{
int st,dr,level;
int i;
long long cod,val;
}v[2000001];
int nheap;
vector<nod> vv;
void up(int k)
{
while(k>1 and vv[k].val<vv[k/2].val)
{
swap(vv[k],vv[k/2]);
k=k/2;
}
}
void down(int nn,int k)
{
bool ok=true;
int j;
while(ok)
{
ok=false;
j=k;
if(k*2<=nn)
{
j=2*k;
if(2*k+1<=nn)
{
if(vv[2*k].val>vv[2*k+1].val)
j=2*k+1;
}
if(vv[k].val>vv[j].val)
{
swap(vv[k],vv[j]);
k=j;
ok=true;
}
}
}
}
void Add(nod val)
{
vv[nheap+1]=val;
nheap++;
up(nheap);
}
void Remove(int k)
{
vv[k]=vv[nheap];
nheap--;
if(k==1)
down(nheap,k);
else
if(vv[k].val<vv[k/2].val)
up(k);
else
down(nheap,k);
}
void createArbore()
{
//luam cele mai mici 2 noduri dupa val
int i,j,ii;
nod copie;
m=n;
// in v avem toate nodurile(nu sunt sortate)
//in vv avem mereu in vv[1] nodul cu vv.val minim
//cream legaturi intre nodurile din v (arborele)
for(ii=1;ii<m;ii++)
{
//cream un nod nou
n++;
v[n].i=n;
v[n].val=vv[1].val;
v[n].st=vv[1].i;
Remove(1);
v[n].val+=vv[1].val;
v[n].dr=vv[1].i;
Remove(1);
Add(v[n]);
suma+=v[n].val;
//am putea calcula suma si in codeaza01 adunand
// v[i].level*v[i].val daca i face parte din elementele initiale
//dar vv esye ca un arbore si pentru ca atunci cand cream un element mai adunam
//inca o data ce aveam deja sub el si asa se obtine tot level*val
}
}
void codeaza01(int poz,long long cod,int level)
{
v[poz].cod=cod;
v[poz].level=level;
level++;
cod=(cod<<1);
if(v[poz].st)
{
codeaza01(v[poz].st,cod,level);
}
if(v[poz].dr)
{
cod++;
codeaza01(v[poz].dr,cod,level);
}
}
int main()
{
int i,j,z,k,x,L;
f>>n;
vv.resize(2*n+1);
nheap=n;
m=n;
for(i=1;i<=n;i++)
{
f>>v[i].val;
v[i].i=i;
vv[i]=v[i];
}
createArbore();
codeaza01(n,0,0);
g<<suma<<'\n';
for(i=1;i<=m;i++)
{
g<<v[i].level<<" "<<v[i].cod<<'\n';
}
}