Cod sursa(job #2562240)

Utilizator memecoinMeme Coin memecoin Data 29 februarie 2020 12:58:35
Problema Nums Scor 5
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.12 kb
#include <fstream>
#include <iomanip>
#include <string>
#include <stdio.h>
#include <vector>
#include <algorithm>
#include <math.h>
#include <set>
#include <map>
#include <string.h>
#include <queue>
#include <stack>

#define INF 0x3f3f3f3f

using namespace std;

#ifdef DEBUG
string name = "data";
#else
string name = "nums";
#endif

ifstream fin(name + ".in");
ofstream fout(name + ".out");

int t = 1;

class Trie {
public:
    Trie *children[10];

    int endNodeOf = 0;
    
    int len = 0;
    
    void insert(string s, int k) {
        
        len++;
        
        if (s.size() == k) {
            endNodeOf = t;
            return;
        }
        
        char c = s[k] - '0';
        
        if (children[c] == NULL) {
            children[c] = new Trie();
        }
        
        children[c]->insert(s, k + 1);
    }
    
    bool contains(string s, int k) {
        if (s.size() == k) {
            return endNodeOf != 0;
        }
        
        char c = s[k] - '0';
        
        if (children[c] == NULL) {
            return false;
        }
        
        return children[c]->contains(s, k + 1);
    }
    
    void printKth(int k, int l) {
        int s = 0;
        for (int i = 0; i <= 9; ++i) {
            if (children[i] == NULL) {
                continue;
            }
            if (s + children[i]->len >= k) {
                fout << i;
                children[i]->printKth(k - s, l);
                break;
            }
            s += children[i]->len;
        }
    }
};

int n;
map<int, Trie*> tries;

#define MAXN 100005
int aib[MAXN];

inline int nrz(int x) {
    return x & (~x + 1);
}

void update(int x) {
    while (x <= n ) {
        aib[x]++;
        x += nrz(x);
    }
}

int query(int x) {
    int result = 0;
    
    while (x > 0) {
        result += aib[x];
        x -= nrz(x);
    }
    
    return result;
}

pair<int, int> findLowest(int low, int high, int x) {
    
    if (low > high) {
        return {-1, -1};
    }
    
    int mid = (low + high) / 2;
    
    int v = query(mid);
    
    if (v >= x) {
        int nxt = query(mid - 1);
        if (nxt < v) {
            return { mid, nxt };
        } else {
            return findLowest(low, mid - 1, x);
        }
    }
    
    return findLowest(mid + 1, high, x);
}

int main() {
    
    fin >> n;
    
    int high = 0;
    int low = INF;
    
    for (int i = 0; i < n; ++i) {
        int op;
        fin >> op;
        if (op == 1) {
            string s;
            fin >> s;
            int x = (int)s.size();
            if (tries[x] == NULL) {
                tries[x] = new Trie();
            }
            auto trie = tries[x];
            if (!trie->contains(s, 0)) {
                trie->insert(s, 0);
                t++;
            }
            update(x);
            high = max(high, (int)s.size());
            low = min(low, (int)s.size());
        } else {
            int k;
            fin >> k;
        
            auto rez = findLowest(low, high, k);
            
            auto trie = tries[rez.first];
            
            trie->printKth(k - rez.second, rez.first);
            fout << "\n";
        }
    }
    
    return 0;
}