#include #include using namespace std; using namespace atcoder; using ll = long long; using P = pair; using mint = modint998244353; #define rep(i, a, b) for(ll i = a; i < b; i++) #define rrep(i, a, b) for(ll i = a; i >= b; i--) constexpr ll inf = 4e18; using T = P; struct SelfBalancingBinarySearchTree { SelfBalancingBinarySearchTree(vector vec = {}) : root(nullptr), MaxNodeCount(0) { for(T x : vec) { insert(x); } } bool find(const T& key) { return find(root, key); } int size() { return size(root); } void insert(const T& key) { insert(root, key); MaxNodeCount = max(MaxNodeCount, size(root)); } void erase(const T& key) { bool is_find = false; Node* connect = nullptr; erase(root, key, is_find, connect); if(size(root) < 0.7 * MaxNodeCount) { vector value; subtree(root, value); rebuild(root, value.begin(), value.end()); MaxNodeCount = size(root); } } int lower_bound(const T& key) { return lower_bound(root, key); } int upper_bound(const T& key) { return upper_bound(root, key); } T get(int idx) { return get(root, idx); } private: struct Node { T key; int count = 1; Node* child[2] = {nullptr, nullptr}; Node(const T& val) : key(val) {} }; Node* root; int MaxNodeCount; bool find(Node* cur, const T& key) const { while(cur) { if(key == cur->key) return true; else if(key < cur->key) cur = cur->child[0]; else cur = cur->child[1]; } return false; } inline int size(Node*& cur) const { if(!cur) return 0; return cur->count; } void insert(Node*& cur, const T& key) { if(!cur) { cur = new Node(key); } else if(key < cur->key) { insert(cur->child[0], key); } else if(key > cur->key) { insert(cur->child[1], key); } cur->count = size(cur->child[0]) + size(cur->child[1]) + 1; if(size(cur->child[0]) > 0.7 * size(cur) or size(cur->child[1]) > 0.7 * size(cur)) { vector value; subtree(cur, value); rebuild(cur, value.begin(), value.end()); } } void erase(Node*& cur, const T& key, bool& is_find, Node*& connect) { if(!cur) { return; } else if(key < cur->key) { erase(cur->child[0], key, is_find, connect); if(is_find) { Node* tmp = cur->child[0]; cur->child[0] = connect; delete tmp; is_find = false; connect = nullptr; } } else if(key > cur->key) { erase(cur->child[1], key, is_find, connect); if(is_find) { Node* tmp = cur->child[1]; cur->child[1] = connect; delete tmp; is_find = false; connect = nullptr; } } else { if(cur->child[0] and cur->child[1]) { T nex_key = get(upper_bound(key)); erase(root, nex_key, is_find, connect); cur->key = nex_key; } else { if(cur->child[0]) connect = cur->child[0]; else if(cur->child[1]) connect = cur->child[1]; is_find = true; if(cur == root) { root = connect; is_find = false; connect = nullptr; return; } } } cur->count = size(cur->child[0]) + size(cur->child[1]) + 1; return; } int lower_bound(Node*& cur, const T& key) const { if(!cur) return 0; if(key == cur->key) return size(cur->child[0]); if(key < cur->key) return lower_bound(cur->child[0], key); else return size(cur->child[0]) + lower_bound(cur->child[1], key) + 1; } int upper_bound(Node*& cur, const T& key) const { if(!cur) return 0; if(key == cur->key) return size(cur->child[0]) + 1; if(key < cur->key) return upper_bound(cur->child[0], key); else return size(cur->child[0]) + upper_bound(cur->child[1], key) + 1; } T get(Node*& cur, int idx) const { assert(0 <= idx and idx < size(cur)); if(idx == size(cur->child[0])) return cur->key; else if(idx < size(cur->child[0])) return get(cur->child[0], idx); else return get(cur->child[1], idx - size(cur->child[0]) - 1); } using Iter = vector::iterator; void rebuild(Node*& cur, Iter begin, Iter end) { int Size = int(end - begin); if(Size == 0) { cur = nullptr; return; } Iter mid = begin + Size / 2; cur = new Node(*mid); rebuild(cur->child[0], begin, mid); rebuild(cur->child[1], mid + 1, end); cur->count = size(cur->child[0]) + size(cur->child[1]) + 1; } void subtree(Node*& cur, vector& val) const { if(!cur) return; subtree(cur->child[0], val); val.push_back(cur->key); subtree(cur->child[1], val); } }; int main(void) { cin.tie(0); ios::sync_with_stdio(0); int Q, K; cin >> Q >> K; SelfBalancingBinarySearchTree tree; map mp; while(Q--) { int t; cin >> t; if(t == 1) { ll v; cin >> v; mp[v]++; tree.insert(P(v, mp[v])); } else { if((int)tree.size() < K) { cout << -1 << '\n'; } else { P ans = tree.get(K - 1); cout << ans.first << '\n'; tree.erase(ans); } } } }