Cod sursa(job #2792236)

Utilizator OrzaSERBANSerban Orza OrzaSERBAN Data 1 noiembrie 2021 11:02:30
Problema Coduri Huffman Scor 65
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.58 kb
#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';
    }

}