#include <iostream>
#include <vector>
#include <math.h>
using namespace std;
int n, m, x, op, f, s;
vector<int> A;
int M[10000001];
void initialize(int nod, int i, int j){
if (i == j) M[nod] = i;
else{
initialize(2 * nod, i, (i + (j - i) / 2));
initialize(2 * nod + 1, (i + (j - i) / 2) + 1, j);
if(A[M[2 * nod]] >= A[M[2 * nod + 1]]){
M[nod] = M[2 * nod];
}else{
M[nod] = M[2 * nod + 1];
}
}
}
int query(int nod, int b, int e, int f, int s){
if (e < f || s < b) return -1;
if (b >= f && e <= s) return M[nod];
int p1 = query(2 * nod, b, (b + e) / 2, f, s);
int p2 = query(2 * nod + 1, (b + e) / 2 + 1, e, f, s);
//return the position where the overall
//minimum is
if (p1 == -1)
return p2;
if (p2 == -1)
return p1;
if (A[p1] >= A[p2])
return p1;
return p2;
}
void propagate(int nod, int b, int e, int pos, int val){
if(b == e && e == pos){ A[M[nod]] = val; return ; }
int m = b + (e-b)/2;
if(pos >= b && pos <= m){
propagate(2*nod, b, m, pos, val);
}else{
propagate(2*nod+1, m+1, e, pos, val);
}
if(A[M[2 * nod]] >= A[M[2 * nod + 1]]){
M[nod] = M[2 * nod];
}else{
M[nod] = M[2 * nod + 1];
}
}
int main(){
freopen("arbint.in", "r", stdin);
freopen("arbint.out", "w", stdout);
scanf("%d%d", &n, &m);
//cin >> n >> m;
for (int i = 0; i < n; i++){
scanf("%d", &x);
//cin >> x;
A.push_back(x);
}
initialize(1, 0, n - 1);
for (int i = 0; i < m; i++){
//cin >> op >> f >> s;
scanf("%d%d%d", &op, &f, &s);
f--, s--;
switch (op){
case 0:
cout << A[query(1, 0, n-1, f, s)] << "\n";
break;
case 1:
propagate(1, 0, n-1, f, s+1);
}
}
return 0;
}