#include<cstdio>
#include<climits>
using namespace std;
int arb[400000], n, m;
void update(int elem, int val, int currentNode, int left, int right) {
if(left < right) {
// nu sunt in frunza, coboara
int mid = (left + right) / 2;
if(elem <= mid) {
update(elem, val, 2 * currentNode, left, mid);
} else {
update(elem, val, 2 * currentNode + 1, mid + 1, right);
}
// dupa ce am updatat fiii, modifica nodul curent
arb[currentNode] = (arb[2 * currentNode] > arb[2 * currentNode + 1]) ? arb[2 * currentNode] : arb[2 * currentNode + 1];
} else {
// frunza
arb[currentNode] = val;
}
}
// cauta maximul din intervalul [a, b] in nodul currentNode, care retine inf. despre [left, right]
int query(int a, int b, int left, int right, int currentNode) {
if(a <= left && right <= b) {
return arb[currentNode];
}
int mid = (left + right) / 2;
int maxLeft, maxRight;
maxLeft = maxRight = INT_MIN;
if(a <= mid) maxLeft = query(a, b, left, mid, 2*currentNode);
if(b > mid) maxRight = query(a, b, mid+1, right, 2*currentNode+1);
return (maxLeft > maxRight) ? maxLeft : maxRight;
}
int main() {
freopen("arbint.in", "r", stdin);
freopen("arbint.out", "w", stdout);
int i, tip, a, b;
scanf("%d %d", &n, &m);
for(i = 1; i <= n; i++) {
scanf("%d", &a);
update(i, a, 1, 1, n);
}
for(i = 1; i <= m; i++) {
scanf("%d %d %d", &tip, &a, &b);
if(tip == 1) {
update(a, b, 1, 1, n);
} else {
printf("%d\n", query(a, b, 1, n, 1));
}
}
return 0;
}