Pagini recente » Cod sursa (job #1412762) | Cod sursa (job #2288405) | Monitorul de evaluare | Cod sursa (job #25538) | Cod sursa (job #1166865)
#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;
}