#include using namespace std; template struct Treap { private: unsigned int xorshift() { static unsigned int x = 123456789, y = 362436069, z = 521288629, w = 88675123; unsigned int t = (x ^ (x << 11)); x = y; y = z; z = w; return (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8))); } struct Node { Node *left, *right; T value, mx; int priority, size; Node (T value_, int priority_) : left(nullptr), right(nullptr), value(value_), mx(value_), priority(priority_), size(1) {} }; using N = Node *; N root = nullptr; T INF = numeric_limits::max(); bool multi; map mp; int cnt(N t) { return t ? t->size : 0; } T get_max(N t) { return t ? t->mx : -INF; } void update(N t) { if (t) { t->size = cnt(t->left) + cnt(t->right) + 1; t->mx = max({t->value, get_max(t->left), get_max(t->right)}); } } void merge(N &t, N l, N r) { if (!l || !r) { t = l ? l : r; } else if (l->priority > r->priority) { merge(l->right, l->right, r); t = l; } else { merge(r->left, l, r->left); t = r; } update(t); } void split(N t, T x, N &l, N &r) { if (!t) { l = nullptr; r = nullptr; } else if (x < t->value) { split(t->left, x, l, t->left); r = t; } else { split(t->right, x, t->right, r); l = t; } update(t); } void insert(N &t, N n) { if (!t) { t = n; } else if (n->priority > t->priority) { split(t, n->value, n->left, n->right); t = n; } else { insert(n->value < t->value ? t->left : t->right, n); } update(t); } void erase(N &t, T x) { if (t->value == x) { merge(t, t->left, t->right); } else { erase(x < t->value ? t->left : t->right, x); } update(t); } bool count(N &t, T x) { if (!t) { return false; } else if (t->value == x) { return true; } else { return count(x < t->value ? t->left : t->right, x); } } T kth(N t, int k) { int sz = cnt(t->left); if (sz == k) { return t->value; } return (sz > k ? kth(t->left, k) : kth(t->right, k - sz - 1)); } pair search(N t, T x, int i, bool equal) { if (equal && t->value == x) { return {t->value, i}; } else if (x < t->value) { if ((equal && x <= get_max(t->left)) || (!equal && x < get_max(t->left))) { return search(t->left, x, i - cnt(t->left->right) - 1, equal); } else { return {t->value, i}; } } else { if (!(t->right)) { return {INF, -1}; } return search(t->right, x, i + cnt(t->right->left) + 1, equal); } } void dump(N t) { if (!t) { return; } dump(t->left); cout << t->value << " "; dump(t->right); } public: Treap(bool multi_ = false) : multi(multi_) {} Treap(vector v, bool multi_ = false) : multi(multi_) { for (auto x : v) { insert(x); } } void insert(T x) { if (!multi && mp[x] > 0) { return; } mp[x]++; insert(root, new Node(x, xorshift())); } void erase(T x) { if (mp[x] > 0) { mp[x]--; erase(root, x); } } bool count(T x) { return count(root, x); } int size() { return cnt(root); } T operator[](int i) { assert(0 <= i && i < cnt(root)); return kth(root, i); } pair lower(T x) { if (!root) { return {INF, -1}; } return search(root, x, cnt(root->left), true); } pair upper(T x) { if (!root) { return {INF, -1}; } return search(root, x, cnt(root->left), false); } void dump() { dump(root); cout << endl; } }; using lint = long long; int main() { int n, q; cin >> n >> q; vector a(n); for (int i = 0; i < n; i++) { cin >> a[i]; } Treap tr(a, true); vector b(n, -1); queue> wait; while (q--) { int t; cin >> t; if (t == 1) { int k; lint x; cin >> k >> x; k--; b[k] = x; wait.push({k, x}); } else if (t == 2) { while (!wait.empty()) { auto [k, x] = wait.front(); wait.pop(); if (b[k] != x) { continue; } b[k] = -1; tr.erase(tr[k]); tr.insert(x); } } else { int k; cin >> k; k--; cout << (b[k] != -1 ? b[k] : tr[k]) << endl; } } }