Pagini recente » Cod sursa (job #1364481) | Cod sursa (job #2285249) | Cod sursa (job #2263111) | Cod sursa (job #2489958) | Cod sursa (job #2562794)
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <string>
#include <vector>
#include <fstream>
using namespace std;
ifstream in("nums.in");
ofstream out("nums.out");
struct query {
int opType;
int key;
string s;
int K;
};
vector<query> queries;
vector<pair<int, string>> strings;
int totalOps;
struct node {
int key;
int priority;
int size;
node* leftChild;
node* rightChild;
node() {}
node(int _key) {
key = _key;
priority = rand();
leftChild = rightChild = NULL;
}
};
typedef node* pnode;
int getSize(pnode node) {
if (node == NULL) {
return 0;
}
return node -> size;
}
void updateSize(pnode node) {
if (node != NULL) {
node -> size = 1 + getSize(node -> leftChild) + getSize(node -> rightChild);
}
}
pair<pnode, pnode> split(pnode root, int key) {
if (root == NULL) {
return {NULL, NULL};
}
if (key < root -> key) {
pair<pnode, pnode> leftSplit = split(root -> leftChild, key);
root -> leftChild = leftSplit.second;
updateSize(root);
return {leftSplit.first, root};
}
pair<pnode, pnode> rightSplit = split(root -> rightChild, key);
root -> rightChild = rightSplit.first;
updateSize(root);
return {root, rightSplit.second};
}
pnode merge(pnode leftTree, pnode rightTree) {
if (leftTree == NULL || rightTree == NULL) {
return (leftTree == NULL) ? rightTree : leftTree;
}
if (leftTree -> priority > rightTree -> priority) {
leftTree -> rightChild = merge(leftTree -> rightChild, rightTree);
updateSize(leftTree);
return leftTree;
}
rightTree -> leftChild = merge(leftTree, rightTree -> leftChild);
updateSize(rightTree);
return rightTree;
}
pnode search(pnode root, int key) {
if (root == NULL || root -> key == key) {
return root;
}
if (key < root -> key) {
return search(root -> leftChild, key);
}
return search(root -> rightChild, key);
}
pnode insert(pnode root, pnode toInsert) {
if (root == NULL) {
return toInsert;
}
if (toInsert -> priority > root -> priority) {
pair<pnode, pnode> splitByInsertionKey = split(root, toInsert -> key);
toInsert -> leftChild = splitByInsertionKey.first;
toInsert -> rightChild = splitByInsertionKey.second;
updateSize(toInsert);
return toInsert;
}
if (toInsert -> key < root -> key) {
root -> leftChild = insert(root -> leftChild, toInsert);
} else {
root -> rightChild = insert(root -> rightChild, toInsert);
}
updateSize(root);
return root;
}
pnode insert(pnode root, int key) {
pnode prevNode = search(root, key);
if (prevNode == NULL) {
root = insert(root, new node(key));
}
return root;
}
pnode findKth(pnode root, int K) {
if (root == NULL) {
return NULL;
}
int currNodeIdx = getSize(root -> leftChild) + 1;
if (K == currNodeIdx) {
return root;
} else if (K < currNodeIdx) {
return findKth(root -> leftChild, K);
}
return findKth(root -> rightChild, K - currNodeIdx);
}
void debug(pnode root) {
if (root == NULL) {
return;
}
debug(root -> leftChild);
out << strings[root -> key].second << " ";
debug(root -> rightChild);
}
void preProcessQueries() {
in >> totalOps;
strings.reserve(totalOps);
queries.reserve(totalOps);
for (int opIdx = 0; opIdx < totalOps; opIdx++) {
query query;
in >> query.opType;
if (query.opType == 1) {
in >> query.s;
strings.push_back({query.s.size(), query.s});
} else {
in >> query.K;
}
queries.push_back(query);
}
sort(strings.begin(), strings.end());
strings.erase(unique(strings.begin(), strings.end()), strings.end());
for (int opIdx = 0; opIdx < totalOps; opIdx++) {
if (queries[opIdx].opType == 1) {
pair<int, string> entry = {queries[opIdx].s.size(), queries[opIdx].s};
queries[opIdx].key = lower_bound(strings.begin(), strings.end(), entry) - strings.begin();
}
}
}
int main() {
srand(time(0));
preProcessQueries();
pnode root = NULL;
for (int opIdx = 0; opIdx < totalOps; opIdx++) {
if (queries[opIdx].opType == 1) {
root = insert(root, queries[opIdx].key);
} else {
pnode kThElement = findKth(root, queries[opIdx].K);
string s = strings[kThElement -> key].second;
out << s << "\n";
}
}
return 0;
}