This documentation is automatically generated by online-judge-tools/verification-helper
#define PROBLEM "https://yukicoder.me/problems/no/2809"
#include <bits/stdc++.h>
using namespace std;
#include "../../lib/data_structure/static_ordered_set.hpp"
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, q; cin >> n >> q;
vector<long long> a(n);
for(int i = 0; i < n; i++){
cin >> a[i];
}
using T = tuple<long long, long long, long long>;
vector<T> query(q);
StaticOrderedSet<long long> ps;
for(auto v : a) ps.add(v);
for(int i = 0; i < q; i++){
int t; cin >> t;
if(t == 1){
int k; long long x; cin >> k >> x;
k--;
query[i] = {t, k, x};
ps.add(x);
} else if(t == 2){
query[i] = {t, -1, -1};
} else{
int k; cin >> k;
k--;
query[i] = {t, k, -1};
}
}
ps.build();
map<int, long long> mp;
for(int i = 0; i < n; i++){
ps.insert(a[i]);
mp[i] = a[i];
}
for(int i = 0; i < q; i++){
long long t, k, x; tie(t, k, x) = query[i];
if(t == 1){
mp[k] = x;
} else if(t == 2){
vector<long long> erase, add;
for(auto [key, val] : mp){
erase.push_back(ps.kth_small_element(key + 1));
add.push_back(val);
}
for(auto v : erase){
ps.erase(v);
}
for(auto v : add){
ps.insert(v);
}
mp.clear();
} else{
if(mp.count(k)){
cout << mp[k] << '\n';
continue;
}
cout << ps.kth_small_element(k + 1) << '\n';
}
}
}
#line 1 "test/yukicoder/yuki_2809.test.cpp"
#define PROBLEM "https://yukicoder.me/problems/no/2809"
#include <bits/stdc++.h>
using namespace std;
#line 2 "lib/data_structure/static_ordered_set.hpp"
/**
* @brief Static Ordered Set
*/
#line 9 "lib/data_structure/static_ordered_set.hpp"
template <typename T>
struct StaticOrderedSet{
struct compress{
std::vector<T> sorted, compressed;
compress(){}
void init(const std::vector<T> &vec){
int n = vec.size();
compressed.resize(n);
for(T x : vec){
sorted.emplace_back(x);
}
std::sort(sorted.begin(), sorted.end());
sorted.erase(unique(sorted.begin(), sorted.end()), sorted.end());
for(int i = 0; i < n; ++i){
compressed[i] = std::lower_bound(sorted.begin(), sorted.end(), vec[i]) - sorted.begin();
}
}
int get(const T &x) const{
return std::lower_bound(sorted.begin(), sorted.end(), x) - sorted.begin();
}
T inv(const T &x) const{
return sorted[x];
}
size_t size() const{
return sorted.size();
}
std::vector<T> getCompressed() const{
return compressed;
}
};
struct BinaryIndexedTree{
int N;
std::vector<T> BIT;
BinaryIndexedTree() {}
void init(int size){
N = size;
BIT.assign(N + 1, 0);
}
T get(int i){
return sum(i + 1) - sum(i);
}
void add(int i, T x){
i++;
while(i <= N){
BIT[i] += x;
i += i & -i;
}
}
T sum(int i) const {
T ans = 0;
while(i > 0){
ans += BIT[i];
i -= i & -i;
}
return ans;
}
T sum(int L, int R) const {
return sum(R) - sum(L);
}
int lower_bound(T x) const {
if(x <= 0){
return 0;
} else{
int v = 0, r = 1;
while(r < N) r = r << 1;
for(int len = r; len > 0; len = len >> 1){
if(v + len < N && BIT[v + len] < x){
x -= BIT[v + len];
v += len;
}
}
return v;
}
}
int upper_bound(T x) const {
if(x < 0){
return 0;
} else{
int v = 0, r = 1;
while(r <= N) r = r << 1;
for(int len = r; len > 0; len = len >> 1){
if(v + len <= N && BIT[v + len] <= x){
x -= BIT[v + len];
v += len;
}
}
return v;
}
}
T operator [](int i) const {
return sum(i, i + 1);
}
};
std::vector<T> a;
compress comp;
T siz, sum;
BinaryIndexedTree cnt, val;
StaticOrderedSet(){ }
void add(T x){
a.push_back(x);
}
void build(){
comp.init(a);
siz = T(0);
sum = T(0);
cnt.init(comp.size());
val.init(comp.size());
}
T size(){
return siz;
}
T all_sum(){
return sum;
}
void insert(T x, T count = 1){
int idx = comp.get(x);
cnt.add(idx, count);
val.add(idx, count * x);
siz += count;
sum += count * x;
}
void erase(T x, T count = 1){
T idx = comp.get(x);
if(cnt.get(idx) < count){
count = cnt.get(idx);
}
cnt.add(idx, -count);
val.add(idx, -count * x);
siz -= count;
sum -= count * x;
}
// 1-indexed
T kth_small_element(T k){
if(k <= 0 || size() < k){
return -1;
}
T idx = cnt.lower_bound(k);
return comp.inv(idx);
}
T kth_large_element(T k){
if(k <= 0 || size() < k){
return -1;
}
T rev_k = size() - k + 1;
return kth_small_element(rev_k);
}
// 1-indexed
T kth_small_sum(T k){
if(size() < k){
return val.sum((int) comp.size());
}
T idx = cnt.lower_bound(k);
T sum = val.sum(idx);
sum += comp.inv(idx) * (k - cnt.sum(idx));
return sum;
}
T kth_large_sum(T k){
if(size() < k){
return val.sum((int) comp.size());
}
T rev_k = size() - k;
return val.sum((int) comp.size()) - kth_small_sum(rev_k);
}
// x 未満
T count_less(T x){
return cnt.sum(comp.get(x));
}
// x 以上
T count_moreq(T x){
return size() - count_less(x);
}
T val_less(T x){
return val.sum(comp.get(x));
}
T val_moreq(T x){
return all_sum() - val_less(x);
}
T lower_bound(T x){
return kth_small_element(count_less(x) + 1);
}
T upper_bound(T x){
return kth_small_element(count_less(x + 1) + 1);
}
// x 以下で最大
T reverse_lower_bound(T x){
return kth_small_element(count_less(x + 1));
}
bool exist(T x){
return count_less(x) != count_less(x + 1);
}
};
#line 6 "test/yukicoder/yuki_2809.test.cpp"
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, q; cin >> n >> q;
vector<long long> a(n);
for(int i = 0; i < n; i++){
cin >> a[i];
}
using T = tuple<long long, long long, long long>;
vector<T> query(q);
StaticOrderedSet<long long> ps;
for(auto v : a) ps.add(v);
for(int i = 0; i < q; i++){
int t; cin >> t;
if(t == 1){
int k; long long x; cin >> k >> x;
k--;
query[i] = {t, k, x};
ps.add(x);
} else if(t == 2){
query[i] = {t, -1, -1};
} else{
int k; cin >> k;
k--;
query[i] = {t, k, -1};
}
}
ps.build();
map<int, long long> mp;
for(int i = 0; i < n; i++){
ps.insert(a[i]);
mp[i] = a[i];
}
for(int i = 0; i < q; i++){
long long t, k, x; tie(t, k, x) = query[i];
if(t == 1){
mp[k] = x;
} else if(t == 2){
vector<long long> erase, add;
for(auto [key, val] : mp){
erase.push_back(ps.kth_small_element(key + 1));
add.push_back(val);
}
for(auto v : erase){
ps.erase(v);
}
for(auto v : add){
ps.insert(v);
}
mp.clear();
} else{
if(mp.count(k)){
cout << mp[k] << '\n';
continue;
}
cout << ps.kth_small_element(k + 1) << '\n';
}
}
}