Cod sursa(job #2792241)

Utilizator OrzaSERBANSerban Orza OrzaSERBAN Data 1 noiembrie 2021 11:29:34
Problema Coduri Huffman Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.71 kb
#include <bits/stdc++.h>

using namespace std;
ifstream f("huffman.in");//huffman
ofstream g("huffman.out");

int n,m;
long long suma;
struct nod
{
    int st,dr,level;
    int i;
    long long val;
}v[2000002];
struct nodLight
{
    int i;
    long long val;
};
int nheap;
vector<nodLight> vv;
//vector<nod> v;
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)
{
    nheap++;
    vv[nheap].i=val.i;
    vv[nheap].val=val.val;
    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,ii;
    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].val=cod;
    v[poz].level=level;
    if(poz>0)
    {
        level++;
        cod=(cod<<1);
        codeaza01(v[poz].st,cod,level);

        cod++;
        codeaza01(v[poz].dr,cod,level);

    }
}
int main()
{
    int i,j,z,k;
    f>>n;
   // v.resize(n+2);
    vv.resize(2*n+2);
    nheap=n;
    m=n;
   // cout<<1;
    for(i=1;i<=n;i++)
    {
        f>>v[i].val;
        v[i].i=i;
        vv[i].i=v[i].i;
        vv[i].val=v[i].val;
    }
    createArbore();
    codeaza01(n,0,0);
    g<<suma<<'\n';
    for(i=1;i<=m;i++)
    {
        g<<v[i].level<<" "<<v[i].val<<'\n';
    }

}