Cod sursa(job #1887333)

Utilizator laurageorgescuLaura Georgescu laurageorgescu Data 21 februarie 2017 15:37:30
Problema Coduri Huffman Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.83 kb
#include <cstdio>
#include <utility>
#include <algorithm>

using namespace std;

FILE *fin = fopen("huffman.in", "r"), *fout = fopen("huffman.out", "w");

typedef long long i64;

const int nmax = 1e6;
const i64 inf = (1LL << 60);

int n;
int h[nmax + 1];
i64 v[nmax + 1];
int g[2 * nmax + 1][ 2 ];

int f[ 2 ], l[ 2 ];
pair<i64, int> q[ 2 ][nmax + 1];

void dfs (int nod, i64 nr, int _h) {
    int val = -1;
    for (int i = 0; i < 2; ++ i) {
        if (g[ nod ][ i ] != 0) {
            ++ val;
            dfs(g[ nod ][ i ], nr * 2 + val, _h + 1);
        }
    }

    if (val == -1) {
        v[ nod ] = nr;
        h[ nod ] = _h;
    }
}

int main() {
    fscanf(fin, "%d", &n);

    f[ 0 ] = f[ 1 ] = 0; l[ 0 ] = l[ 1 ] = -1;
    for (int i = 1; i <= n; ++ i) {
        i64 x;
        fscanf(fin, "%lld", &x);
        q[ 0 ][ ++ l[ 0 ] ] = make_pair(x, i);
    }

    i64 ans = 0;
    int nr = n;
    while (l[ 0 ] - f[ 0 ] + 1 + l[ 1 ] - f[ 1 ] + 1 > 1) {
        i64 sum = 0;

        ++ nr;
        for (int i = 1; i <= 2; ++ i) {
            i64 mn = inf; int cine = 0;

            for (int j = 0; j < 2; ++ j) {
                if (f[ j ] <= l[ j ] && mn > q[ j ][ f[ j ] ].first) {
                    cine = q[ j ][ f[ j ] ].second;
                    mn = q[ j ][ f[ j ] ].first;
                }
            }

            sum += mn;
            g[ nr ][i - 1] = cine;

            for (int j = 0; j < 2; ++ j) {
                if (f[ j ] <= l[ j ] && q[ j ][ f[ j ] ].second == cine) {
                    ++ f[ j ]; break;
                }
            }
        }

        ans += sum;
        q[ 1 ][ ++ l[ 1 ] ] = make_pair(sum, nr);
    }

    fprintf(fout, "%lld\n", ans);

    dfs(nr, 0, 0);

    for (int i = 1; i <= n; ++ i) {
        fprintf(fout, "%d %lld\n", h[ i ], v[ i ]);
    }

    fclose( fin );
    fclose( fout );
    return 0;
}