Cod sursa(job #2635287)

Utilizator LucaSeriSeritan Luca LucaSeri Data 13 iulie 2020 21:36:21
Problema Coduri Huffman Scor 65
Compilator cpp-32 Status done
Runda Arhiva educationala Marime 3.97 kb
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/detail/standard_policies.hpp>
using namespace std;
using namespace __gnu_pbds;

#define mp make_pair
#define sz(x) (int)((x).size())
#define all(x) (x).begin(),(x).end()
#define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
#define eb emplace_back

typedef pair< int, int > pii;
typedef pair< long long, long long > pll;
typedef long long ll;
typedef unsigned long long ull;
typedef vector< int > vi;
typedef vector< vi > vvi;
typedef vector< ll > vll;
typedef vector< vll > vvll;
typedef vector< pii > vpii;
typedef vector< vpii > vvpii;
typedef vector< pll > vpll;
typedef long double ld;
typedef vector< ld > vld;
typedef unsigned int uint;
 
template <uint MD> struct ModInt {
    using M = ModInt;
    const static M G;
    uint v;
    ModInt(ll _v = 0) { set_v(uint(_v % MD + MD)); }
    M& set_v(uint _v) {
        v = (_v < MD) ? _v : _v - MD;
        return *this;
    }
    explicit operator bool() const { return v != 0; }
    M operator-() const { return M() - *this; }
    M operator+(const M& r) const { return M().set_v(v + r.v); }
    M operator-(const M& r) const { return M().set_v(v + MD - r.v); }
    M operator*(const M& r) const { return M().set_v(uint(ull(v) * r.v % MD)); }
    M operator/(const M& r) const { return *this * r.inv(); }
    M& operator+=(const M& r) { return *this = *this + r; }
    M& operator-=(const M& r) { return *this = *this - r; }
    M& operator*=(const M& r) { return *this = *this * r; }
    M& operator/=(const M& r) { return *this = *this / r; }
    bool operator==(const M& r) const { return v == r.v; }
    const bool operator<(const M& o) const {return v < o.v; }
    M pow(ll n) const {
        M x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    M inv() const { return pow(MD - 2); }
    friend ostream& operator<<(ostream& os, const M& r) { return os << r.v; }
};
 
using Mint = ModInt<(int)1e9 + 7>;

int main() { 
    #ifdef BLAT
        freopen("stdin", "r", stdin);
        freopen("stderr", "w", stderr);
    #else
        FO(huffman);
    #endif

    int n;
    cin >> n;

    if(n == 1) {
        cout << 1 << '\n';
        cout << 1 << ' ' << 0 << '\n';
        return 0;
    }

    vector< vector< pair< int, int > > > gr(1);

    queue< pair< int, int > > ex;
    queue< pair< int, int > > in;

    vector< int > v(n + 1);
    for(int i = 1; i <= n; ++i) {
        cin >> v[i];
        ex.emplace(i, v[i]);
    }

    auto getMin = [&]() {
        if(ex.size() == 0) {
            auto pa = in.front();
            in.pop();
            return pa;
        }
        if(in.size() == 0 || ex.front().second < in.front().second) {
            auto pa = ex.front();
            ex.pop();
            return pa;
        }


        auto pa = in.front();
        in.pop();
        return pa;
    };

    int root = n;

    while(ex.size() + in.size() > 1) {
        auto u = getMin();
        auto v = getMin();

        ++root;
        gr.emplace_back(gr.front());
        gr[root-n].emplace_back(u.first, 0);
        gr[root-n].emplace_back(v.first, 1);

        in.emplace(root, u.second + v.second);
    }


    queue< int > q;
    q.push(root);

    vector< int > lung(root + 1);
    vector< ll > cod(root + 1);

    while(q.size()) {
        int node = q.front();
        q.pop();

        for(auto &x : gr[node-n]) {
            lung[x.first] = lung[node] + 1;
            cod[x.first] = (cod[node]<<1) + x.second;
            if(x.first > n) q.push(x.first);
        }
    }

    ll ans = 0;
    for(int i = 1; i <= n; ++i) {
        ans += 1ll*lung[i]*v[i];
    }

    cout << ans << '\n';

    for(int i = 1; i <= n; ++i) {
        cout << lung[i] << ' ' << cod[i] << '\n';
    }

    return 0;
}