Cod sursa(job #3293502)

Utilizator Sorin_GabrielGabara Sorin Gabriel Sorin_Gabriel Data 11 aprilie 2025 20:26:13
Problema Coduri Huffman Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.13 kb
#include <iostream>
#include <bits/stdc++.h>
#define VMAX 1000005
#define INF 1000000000000000000
using namespace std;
ifstream fin ("huffman.in");
ofstream fout ("huffman.out");

vector<long long int> de_adg; // aici vor fi, in ordine, de la mare la mic, toate valorile nodurilor care trb adaugate in copac
queue<long long int> noduri;
queue<int> litere;
vector<int> valori_litere;
struct ap{
int lg,aparitii;
long long int val;
};
ap identifica[VMAX]; // valorile finale ale simbolurilor


int getmin() // returneaza nodul sau simbolul cu valoarea minima din cele ramase
{
    long long int i=INF,j=INF;
    if(noduri.size())
        j=noduri.front();
    if(litere.size())
        i=litere.front();

    if(j==INF)
    {
        de_adg.push_back(identifica[i].aparitii); // odata ales, il putem adauga in lista
        litere.pop();
        return identifica[i].aparitii;
    }
    else if(i==INF)
    {
        noduri.pop();
        de_adg.push_back(j); // odata ales, il putem adauga in lista
        return j;
    }
    if(identifica[i].aparitii<=j)
    {
        de_adg.push_back(identifica[i].aparitii);
        litere.pop();
        return identifica[i].aparitii;
    }
    else
    {
        noduri.pop();
        de_adg.push_back(j);
        return j;
    }
}

void build()
{
    // pentru a reconstrui solutia, vom face o parcurgere pe nivele, iar daca o valoarea este egala cu a unui caracter, o vom inlocui
    long long int nr, mij;
    queue<pair<int,long long int>> qq;
    pair<int,long long int>nod;
    qq.push({0,0});
    while(de_adg.size()) // cat timp nu am mers prin fiecare valoare nod, nu am terminat parcurgerea
    {
        // valori_litere e sortat crescator, la fel ca de_adg
        //deci stim ca urmatorul simbol cautat va fi ultimul simbol pe care nu l-am intalnit
        //prima data cand intalnim o valoare din adg==un simbol, atribuim simbolului valoarea gasita, greedy
        nod=qq.front();
        qq.pop();
        nr=de_adg.back();
        de_adg.pop_back();


        if(valori_litere.back()==nr) // am gasit aparitia unui caracter
        {
            valori_litere.pop_back();
            identifica[valori_litere.size()].lg=nod.first;
            identifica[valori_litere.size()].val=nod.second;
        }
        else // e un nod
        {
            qq.push({nod.first+1,nod.second*2});
            qq.push({nod.first+1,nod.second*2+1});
        }
    }
}


signed main()
{
    long long int n,m,i,j,k,t,q,nr;
    fin>>n;
    valori_litere.push_back(0);
    for(i=1;i<=n;i++)
    {
        fin>>j;
        valori_litere.push_back(j);
        identifica[i].aparitii=j;
        litere.push(i);
    }

    while(litere.size() + noduri.size()>1)
    {
        i = getmin();
        j = getmin();
        noduri.push(i+j);
    }
    de_adg.push_back(noduri.front());
    build(); // vom reconstrui "arborele"

    nr=0;
    for(i=1;i<=n;i++)
    {
        nr+=identifica[i].aparitii*identifica[i].lg;
    }
    fout<<nr<<'\n';
    for(i=1;i<=n;i++)
        fout<<identifica[i].lg<<' '<<identifica[i].val<<'\n';



    return 0;
}