#include <stdio.h>
using namespace std;
inline int maxim(int a, int b) {
if (a > b)
return a;
return b;
}
int construieste_arbint(int st, int dr, int *arb, int indice, int *A) {
if (st == dr) {
arb[indice] = A[st];
return A[st];
}
int mij = st + (dr - st) / 2, a, b;
a = construieste_arbint(st, mij, arb, 2 * indice + 1, A); // mergem pe primul fiu in arbore, indexarea incepe de la 0 deci fiul stang va fi 2 * i + 1
b = construieste_arbint(mij + 1, dr, arb, 2 * indice + 2, A); // mergem pe al doilea fiu
arb[indice] = maxim(a, b);
return maxim(a, b);
}
void actualizeaza(int st, int dr, int a, int b, int *arb, int indice) {
if (st == dr) {
if (st == a) {
arb[indice] = b;
return;
}
else
return;
}
int mij = st + (dr - st) / 2;
if (st <= a && a <= dr) {
actualizeaza(st, mij, a, b, arb, 2 * indice + 1);
actualizeaza(mij + 1, dr, a, b, arb, 2 * indice + 2);
arb[indice] = maxim(arb[2 * indice + 1], arb[2 * indice + +2]); //reactualizam maximul pe fiecare interval care continea pozitia a
}
}
int interogheaza(int st, int dr, int a, int b, int *arb, int indice) {
if (a <= st && dr <= b)
return arb[indice];
int mij = st + (dr - st) / 2, x = -1, y = -1;
if (a <= mij)
x = interogheaza(st, mij, a, b, arb, indice * 2 + 1);
if (b > mij)
y = interogheaza(mij + 1, dr, a, b, arb, indice * 2 + 2);
//if (x == -1 && y == -1)
// return -1;
return maxim(x, y);
}
int main() {
freopen("arbint.in", "r", stdin);
freopen("arbint.out", "w", stdout);
int n, m, cod, a, b;
scanf("%d %d", &n, &m);
int A[n], arb[4 * n - 1] = {0};
for (int i = 0; i < n; i++)
scanf("%d", &A[i]);
arb[0] = construieste_arbint(0, n - 1, arb, 0, A);
for (int i = 0; i < m; i++) {
scanf("%d %d %d", &cod, &a, &b);
if (cod == 0)
printf("%d\n", interogheaza(0, n - 1, a - 1, b - 1, arb, 0));
if (cod == 1)
actualizeaza(0, n - 1, a - 1, b, arb, 0);
}
return 0;
}