Cod sursa(job #1166865)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 3 aprilie 2014 21:37:42
Problema Coduri Huffman Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.69 kb
#include <cstdio>
#include <cstring>
#include <cassert>

#include <algorithm>
#include <queue>

using namespace std;

typedef long long int64;

class Reader {
  public:
    Reader(FILE *_stream, const int _size = (1 << 16)):
      size(_size),
      pointer(0),
      buffer(new char[_size]),
      stream(_stream) {
        assert(fread(buffer, 1, size, stream) != 0);
    }

    template<class IntType>
    IntType NextInt() {
        IntType value = 0;
        bool negative = false;
        while ((Current() < '0' || Current() > '9') && Current() != '-')
            NextPosition();
        if (Current() == '-') {
            negative = true;
            NextPosition();
        }
        while(Current() >= '0' && Current() <= '9') {
            value = value * 10 + Current() - '0';
            NextPosition();
        }
        if (negative)
            value = -value;
        return value;
    }

    Reader &operator>>(int &value) {
        value = NextInt<int>();
        return *this;
    }

    Reader &operator>>(long long &value) {
        value = NextInt<long long>();
        return *this;
    }

  private:
    int size, pointer;
    char *buffer;
    FILE *stream;

    char Current() const {
        return buffer[pointer];
    }

    void NextPosition() {
        if(++pointer == size) {
            assert(fread(buffer, 1, size, stream) != 0);
            pointer = 0;
        }
    }
};

const int MAX_N = 1000000;
const int NIL = -1;
const int BASE = 2;

int V, Tree[2 * MAX_N][BASE], Levels[2 * MAX_N];
int64 Codes[MAX_N];
int N;
int64 Frequences[MAX_N], TotalLength;

void DFS(const int x, const int64 currentCode) {
    if (x < N)
        Codes[x] = currentCode;
    for (int i = 0; i < BASE && Tree[x][i] != NIL; ++i) {
        Levels[Tree[x][i]] = Levels[x] + 1;
        DFS(Tree[x][i], currentCode * BASE + i);
    }
}

inline pair<int64, int> ExtractFront(queue< pair<int64, int> > &first, queue< pair<int64, int> > &second) {
    pair<int64, int> front;
    if (first.empty()) {
        front = second.front();
        second.pop();
    } else if (second.empty()) {
        front = first.front();
        first.pop();
    } else {
        if (first.front() < second.front()) {
            front = first.front();
            first.pop();
        } else {
            front = second.front();
            second.pop();
        }
    }
    return front;
}

void InitializeTree() {
    memset(Tree, NIL, sizeof(Tree));
    memset(Levels, -1, sizeof(Levels));
    memset(Codes, -1, sizeof(Codes));
}

void GetHuffmanCodes() {
    InitializeTree();
    queue< pair<int64, int> > terminal, internal;
    for (int i = 0; i < N; ++i)
        terminal.push(make_pair(Frequences[i], V++));
    while (int(terminal.size()) + int(internal.size()) > 1) {
        pair<int64, int> x = ExtractFront(terminal, internal);
        pair<int64, int> y = ExtractFront(terminal, internal);
        int z = V++;
        Tree[z][0] = x.second;
        Tree[z][1] = y.second;
        internal.push(make_pair(x.first + y.first, z));
    }
    Levels[V - 1] = 0;
    DFS(V - 1, 0LL);
}

void Solve() {
    GetHuffmanCodes();
    TotalLength = 0;
    for (int i = 0; i < N; ++i)
        TotalLength += Frequences[i] * Levels[i];
}

void Read() {
    assert(freopen("huffman.in", "r", stdin));
    Reader cin = Reader(stdin);
    cin >> N;
    for (int i = 0; i < N; ++i)
        cin >> Frequences[i];
}

void Print() {
    assert(freopen("huffman.out", "w", stdout));
    printf("%lld\n", TotalLength);
    for (int i = 0; i < N; ++i)
        printf("%d %lld\n", Levels[i], Codes[i]);
}

int main() {
    Read();
    Solve();
    Print();
    return 0;
}