#include <fstream>
#include <functional>
#include <bitset>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
using namespace std;
class parser {
public:
inline parser() {
/// default c-tor
}
inline parser(const char* file_name) {
int fd = open(file_name, O_RDONLY);
index &= 0;
fstat(fd, &sb);
buffer = (char*)mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, fd, 0);
close(fd);
}
template <typename T>
inline parser& operator >> (T& n) {
n &= 0;
#ifdef SIGNED
sign &= 0;
sign = (buffer[index - 1] == '-');
#endif
for (; buffer[index] < '0' or buffer[index] > '9'; ++index);
for (; '0' <= buffer[index] and buffer[index] <= '9'; ++index)
n = (n << 3) + (n << 1) + buffer[index] - '0';
#ifdef SIGNED
n ^= ((n ^ -n) & -sign);
#endif
return *this;
}
~parser() {
munmap(buffer, sb.st_size);
}
private:
struct stat sb;
int index;
#ifdef SIGNED
int sign;
#endif
char* buffer;
};
class writer {
public:
writer() {};
writer(const char* file_name) {
output_file.open(file_name, std::ios::out | std::ios::binary);
output_file.sync_with_stdio(false);
index &= 0;
}
template <typename T>
inline writer& operator <<(T target) {
auto inc = [&, this]() mutable {
if (++index == SIZE)
index &= 0,
output_file.write(buffer, SIZE);
};
aux &= 0;
#ifdef SIGNED_WRITE
sign = 1;
if (target < 0)
sign = -1;
#endif // SIGNED_WRITE
if (target == 0) {
buffer[index] = '0';
inc();
return *this;
}
for (; target; target = target / 10)
#ifndef SIGNED_WRITE
nr[aux++] = target % 10 + '0';
#else
nr[aux++] = (sign * target) % 10 + '0';
if (sign == -1)
buffer[index] = '-', inc();
#endif // SIGNED_WRITE
for (; aux; inc())
buffer[index] = nr[--aux];
return *this;
}
inline writer& operator <<(const char* target) {
auto inc = [&, this]() mutable {
if (++index == SIZE)
index &= 0,
output_file.write(buffer, SIZE);
};
aux &= 0;
while (target[aux])
buffer[index] = target[aux++], inc();
return *this;
}
inline void close() {
delete this;
}
~writer() {
output_file.write(buffer, index);
output_file.close();
}
private:
static const int SIZE = 0x400000; ///2MB
int index, aux;
#ifdef SIGNED_WRITE
int sign;
#endif // SIGNED_WRITE
char buffer[SIZE], nr[24];
std::fstream output_file;
};
template <typename Tkey, typename Tinfo, typename comparator, typename infinitum>
class fibonacci_heap {
public:
struct node {
node() { }
node(Tinfo _info, Tkey _key) : key(_key), info(_info) {
after = nullptr;
before = nullptr;
rank = 0;
state = false;
child = nullptr;
parent = nullptr;
}
Tkey key;
Tinfo info;
unsigned rank;
bool state;
node* child, * after, * before, * parent;
};
fibonacci_heap() {
for (auto& i : A) {
i = nullptr;
}
_root = nullptr;
}
node* make_item(Tinfo info, Tkey v) {
return new node(info, v);
}
bool empty() { return root() == nullptr; }
void add(Tinfo _a, Tkey _b) {
root() = meld(make_item(_a, _b), root());
}
void add(node* a) {
root() = meld(a, root());
}
node* pop_node(node* x) {
decrease_key(x, std::invoke(INF));
return pop();
}
node* pop() {
auto x = root()->child;
unsigned max_rank = 0;
root() = x;
while (x != nullptr) {
auto y = x;
x = x->after;
while (A[y->rank] != nullptr) {
y = link(y, A[y->rank]);
A[y->rank] = nullptr;
y->rank = y->rank + 1;
}
A[y->rank] = y;
if (y->rank > max_rank)
max_rank = y->rank;
}
for (unsigned i = 0; i <= max_rank; ++i) {
if (A[i] != nullptr) {
if (x == nullptr)
x = A[i];
else
x = link(x, A[i]);
A[i] = nullptr;
}
}
return x;
}
node* top() {
return root();
}
node* decrease_key(node* x, Tkey v) {
x->key = v;
if (x == root())
return root();
root()->state = false;
decrease_ranks(x);
cut(x);
return link(x, root());
}
private:
node* meld(node* g, node* h) {
if (g == nullptr) return h;
if (h == nullptr) return g;
return link(g, h);
}
node* link(node* x, node* y) {
if (!is_less(x->key, y->key)) {
add_child(x, y);
return y;
}
else {
add_child(y, x);
return x;
}
}
void add_child(node* x, node* y) {
if (x == root())
root() = y;
x->parent = y;
node* z = y->child;
x->before = nullptr;
x->after = z;
if (z != nullptr) {
z->before = x;
}
y->child = x;
}
void cut(node* x) {
node* y = x->parent;
if (y->child == x) {
y->child = x->after;
}
if (x->before != nullptr) {
x->before->after = x->after;
}
if (x->after != nullptr) {
x->after->before = x->before;
}
}
void decrease_ranks(node* y) {
do {
y = y->parent;
if (y->rank > 0) {
y->rank--;
}
y->state = !y->state;
} while (y->state == false);
}
node*& root() { return _root; }
node* _root, * A[200010];
comparator is_less;
infinitum INF;
};
class infinit {
int operator ()() {
return -1;
}
};
parser f("heapuri.in");
writer t("heapuri.out");
int n;
bitset <200010> vaz;
//heap<integer, integer::do_compare> h(200010);
fibonacci_heap<int, int, std::less<int>, infinit> h;
int main() {
f >> n;
for (int query, idx = 0, i = 0; i < n; ++i) {
f >> query;
switch (query) {
case 1: {
f >> query;
++idx;
h.add(idx, query);
break;
}
case 2: {
f >> query;
vaz[query] = true;
break;
}
case 3: {
while (vaz[h.top()->info]) {
h.pop();
}
t << h.top()->key << "\n";
break;
}
}
}
return 0;
}