Cod sursa(job #2120102)

Utilizator laurageorgescuLaura Georgescu laurageorgescu Data 1 februarie 2018 21:43:39
Problema Nums Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.3 kb
#include <fstream>
#include <vector>
#include <queue>
#include <string>

using namespace std;

ofstream fout ("nums.out");

class InputReader {
	public:
        InputReader() {}
        InputReader(const char *name) {
            fin = fopen(name, "r");
			buffpos = Size - 1;
        }
        InputReader &operator >>(int &n) {
			char ch = nextpos();
            while(ch < '0' || ch > '9') {
                ch = nextpos();
            }

            n = 0;
            while('0' <= ch && ch <= '9') {
                n = n * 10 + ch - '0';
                ch = nextpos();
            }
            return *this;
        }
        InputReader &operator >> (string &s) {
			char ch = nextpos();
            while(ch < '0' || ch > '9') {
                ch = nextpos();
            }

            while('0' <= ch && ch <= '9') {
                s += ch;
                ch = nextpos();
            }
            return *this;
        }

    private:
        FILE *fin;
        static const int Size = 1 << 17;
        int buffpos;
        char buff[Size];

        inline char nextpos() {
            ++ buffpos;
            if(buffpos == Size) {
                buffpos = 0;
                fread(buff, Size, 1, fin);
            }
			return buff[ buffpos ];
        }
} fin ("nums.in");

typedef unsigned long long u64;
const int nmax = 1e5;
const int cif = 4;
const int base = 1e4;

int n;
vector< string > v;
vector< int > ord, lg[nmax + 1];

queue< int > q[ 2 ][ base ];
pair<int, int> op[nmax + 1];

int val[nmax + 1];
int aint[4 * nmax + 1];

inline int get (int i, int j) {
    int sum = 0;
    int p10 = 1;
    for (int k = j; k > j - cif && k >= 0; -- k) {
        sum = sum + (v[ i ][ k ] - '0') * p10;
        p10 *= 10;
    }
    return sum;
}

void radix () {
    for (int i = 1; i <= n; ++ i) {
        if (op[ i ].first == 1) {
            int x = op[ i ].second;
            lg[(int)v[ x ].size()].push_back( x );
        }
    }

    for (int j = 1; j <= nmax; ++ j) {
        if (lg[ j ].size() == 0)
            continue;

        for (auto i : lg[ j ]) {
            q[ 0 ][get(i, j - 1)].push( i );
        }

        int ind = 0;
        for (int i = j - 1 - cif; i >= 0; i -= cif, ind = 1 - ind) {
            for (int p = 0; p < base; ++ p) {
                while (!q[ ind ][ p ].empty()) {
                    int x = q[ ind ][ p ].front();
                    q[ ind ][ p ].pop();

                    q[1 - ind][get(x, i)].push( x );
                }
            }
        }


        for (int p = 0; p < base; ++ p) {
            while (!q[ ind ][ p ].empty()) {
                int x = q[ ind ][ p ].front();
                q[ ind ][ p ].pop();

                ord.push_back( x );
            }
        }
    }
}

bool egal (const string &a, const string &b) {
    if (a.size() != b.size())
        return 0;

    for (int i = 0; i < (int)a.size(); ++ i)
        if (a[ i ] != b[ i ])
            return 0;
    return 1;
}

void precalc () {
    radix ();

    for (int i = 0; i < (int)ord.size(); ) {
        int j = i;

        while (j < (int)ord.size() && egal(v[ ord[ i ] ], v[ ord[ j ] ])) {
            val[ ord[ j ] ] = i + 1;
            ++ j;
        }

        i = j;
    }
}

void update (int nod, int x, int y, int pos) {
    if (x == y) {
        aint[ nod ] = 1;
        return ;
    }

    int mij = (x + y) / 2;
    if (pos <= mij)
        update(2 * nod, x, mij, pos);
    else
        update(2 * nod + 1, mij + 1, y, pos);

    aint[ nod ] = aint[2 * nod] + aint[2 * nod + 1];
}

int query (int nod, int x, int y, int k) {
    if (x == y)
        return x;

    int mij = (x + y) / 2;
    if (k <= aint[2 * nod]) {
        return query(2 * nod, x, mij, k);
    } else {
        return query(2 * nod + 1, mij + 1, y, k - aint[2 * nod]);
    }
}

int main () {
    fin >> n;

    for (int i = 1; i <= n; ++ i) {
        fin >> op[ i ].first;

        if (op[ i ].first == 0) {
            fin >> op[ i ].second;
        } else {
            string x;
            fin >> x;
            v.push_back( x );
            op[ i ].second = (int)v.size() - 1;
        }
    }

    precalc ();

    for (int i = 1; i <= n; ++ i) {
        if (op[ i ].first == 0) {
            fout << v[ ord[query(1, 1, n, op[ i ].second) - 1] ] << "\n";
        } else {
            update(1, 1, n, val[ op[ i ].second ]);
        }
    }

    fout.close();
    return 0;
}