Cod sursa(job #972642)

Utilizator narcis_vsGemene Narcis - Gabriel narcis_vs Data 12 iulie 2013 12:20:30
Problema Coduri Huffman Scor 65
Compilator cpp Status done
Runda Arhiva educationala Marime 2.52 kb
#include <fstream>
#include <queue>
#include <cstdio>

#define In "huffman.in"
#define Out "huffman.out"
#define min(a,b) ((a)<(b)?(a):(b))
#define LL long long
#define PLLN pair < LL , node* >
#define PLI pair < LL , int >
#define Nmax 5000010
#define Lim 50000
#define Next (++pos==Lim)?(f.read(Buffer,Lim),pos = 0):0

using namespace std;

struct node
{
    node *l, *r;
    int ind;
    node()
    {
        ind = 0;
        l = r = NULL;
    }
};
PLI sol[Nmax];
node *Root = new node;
queue< PLLN >Q[2];
int N, pos;
LL Sum;
char Buffer[Lim];
ifstream f(In);

inline void Read(int &x)
{
    while(Buffer[pos]<'0' || '9'<Buffer[pos])
        Next;
    x = 0;
    while('0'<=Buffer[pos] && Buffer[pos]<='9')
    {
        x = x*10 +Buffer[pos]-'0';
        Next;
    }
}

inline void Read()
{
    int x;
    node *A;
    Read(N);
    for(int i = 1;i <= N ; ++i)
    {
        Read(x);
        A = new node;
        A->ind = i;
        Q[0].push(make_pair(x,A));
    }
    f.close();
}

inline PLLN Min()
{
    PLLN A;
    A.first = 0;
    if(Q[0].empty())
    {
        if(Q[1].empty())
            return A;
        A = Q[1].front();
        Q[1].pop();
        return A;
    }
    if(Q[1].empty())
    {
        A = Q[0].front();
        Q[0].pop();
        return A;
    }
    if(Q[0].front()<Q[1].front())
    {
        A = Q[0].front();
        Q[0].pop();
    }
    else
    {
        A = Q[1].front();
        Q[1].pop();
    }
    return A;
}

inline void BuildTree()
{
    PLLN X, Y;
    node *A,*Last;
    while(true)
    {
        X = Min();
        Y = Min();
        if(X.first<=0 || Y.first<=0)
        {
            Root = Last;
            return;
        }
        A = new node;
        A->l = X.second;
        A->r = Y.second;
        Sum += X.first+Y.first;
        Last = A;
        Q[1].push(make_pair(X.first+Y.first,A));
    }
}

inline void BuildSol(node *_node,const LL X, const int length)
{
    if(_node->ind)
    {
        sol[_node->ind].first = X;
        sol[_node->ind].second = length;
        return;
    }
    if(_node->l)
        BuildSol(_node->l,(X<<1),length+1);
    if(_node->r)
        BuildSol(_node->r,(X<<1)+1,length+1);
}

inline void Write()
{
    freopen(Out,"w",stdout);
    printf("%lld\n",Sum);
    for(int i = 1;i <= N; ++i)
        printf("%d %lld\n",sol[i].second,sol[i].first);
}

int main()
{
    Read();
    BuildTree();
    BuildSol(Root,0,0);
    Write();
    return 0;
}