Cod sursa(job #1866572)

Utilizator Theodor1000Cristea Theodor Stefan Theodor1000 Data 3 februarie 2017 12:27:45
Problema Coduri Huffman Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.57 kb
#include <cstdio>
#include <algorithm>
#include <cstring>

#define NMAX 100000

using namespace std;


char buffer[NMAX + 10];
int bufpoz = NMAX + 10;

inline void get (int &n);


int g[2000010][2];
int lvl[1000010], unit[2000010], st[1000010];
int n;
long long cost = 0LL, nr[1000010], v[2000010];

inline void dfs (int nod, int lev, long long cif)
{
    if (nod <= n)
    {
        cost += lev * v[nod];

        lvl[nod] = lev;
        nr[nod] = cif;
        return;
    }

    for (int i = 0; i < 2; ++i)
        dfs (g[nod][i], lev + 1, 1LL * cif * 2 + 1LL * i);

}

int main ()
{
    freopen ("huffman.in", "r", stdin);
    freopen ("huffman.out", "w", stdout);

    get (n);

    int k = 0;
    for (int i = 1; i <= n; ++i)
    {
        int x;
        get (x);

        v[++k] = 1LL * x;
        st[++st[0]] = k;
    }

    if (n == 1)
    {
        printf ("%lld\n1 0\n", v[1]);
        return 0;
    }

    int p = 1, q = 1;

    for (; st[0] > p || unit[0] > q || (st[0] >= p && unit[0] >= q);)
    {
        int aa = st[p];
        int bb = st[p + 1];
        int cc = unit[q];
        int dd = unit[q + 1];

        int a, b, poz = 0;
        long long mi = 2000000000000000000LL;
        if (st[0] > p)
        {
            if (mi > v[aa] + v[bb]) mi = v[aa] + v[bb], poz = 1, a = aa, b = bb;
        }

        if (st[0] >= p && unit[0] >= q)
        {
            if (mi > v[aa] + v[cc]) mi = v[aa] + v[cc], poz = 2, a = aa, b = cc;
        }

        if (unit[0] > q)
        {
            if (mi > v[cc] + v[dd]) mi = v[cc] + v[dd], poz = 3, a = cc, b = dd;
        }


        g[++k][0] = a;
        g[k][1] = b;

        if (poz == 1) p += 2;
        if (poz == 2) ++p, ++q;
        if (poz == 3) q += 2;

        unit[++unit[0]] = k;
        v[k] = mi;
    }

    dfs (k, 0, 0);
    printf ("%lld\n", cost);

    for (int i = 1; i <= n; ++i)
        printf ("%d ", lvl[i]),
        printf ("%lld\n", nr[i]);

    return 0;
}

inline void get (int &n)
{
    n = 0;
    if (bufpoz > NMAX)
        fread (buffer, 1, NMAX, stdin), bufpoz = 0;

    int semn = 1;
    while ('0' > buffer[bufpoz] || buffer[bufpoz] > '9')
    {
        if (buffer[bufpoz] == '-') semn = -1;

        if (++bufpoz == NMAX)
            fread (buffer, 1, NMAX, stdin), bufpoz = 0;
    }

    while ('0' <= buffer[bufpoz] && buffer[bufpoz] <= '9')
    {
        n = n * 10 + buffer[bufpoz] - 48;
        if (++bufpoz == NMAX)
            fread (buffer, 1, NMAX, stdin), bufpoz = 0;
    }

    n *= semn;
}