//0 a b: care este maximul din [a, b]?
//1 a b c: toate numerele din intervalul [a, b] devin c
#include <cstdio>
#include <algorithm>
using namespace std;
#define NMAX 100050
#define ns (nod << 1)
#define nd ((nod << 1) + 1)
struct arbint {
int max, nr;
} A[4 * NMAX];
int V[NMAX], tip, n, m, i, a, b, c;
void arbore (int, int, int), update (int, int, int, int, int, int);
int query (int, int, int, int, int);
int main () {
freopen ("arbint.in", "r", stdin);
freopen ("arbint.out", "w", stdout);
scanf ("%d %d", &n, &m);
for (i = 1; i <= n; i++)
scanf ("%d", &V[i]);
for (i = 1; i <= 3 * n; i++) A[i].nr = -1;
arbore (1, 1, n);
for (i = 1; i <= m; i++) {
scanf ("%d", &tip);
if (tip == 0) {
scanf ("%d %d", &a, &b);
printf ("%d\n", query (1, 1, n, a, b));
}
if (tip == 1) {
scanf ("%d %d", &a, &c);
update (1, 1, n, a, a, c);
}
}
return 0;
}
void arbore (int nod, int st, int dr) {
if (st == dr) {
A[nod].max = V[st]; return;
}
int mij = (st + dr) >> 1;
arbore (ns, st, mij);
arbore (nd, mij + 1, dr);
A[nod].max = max (A[ns].max, A[nd].max);
}
void update (int nod, int st, int dr, int a, int b, int nr) {
if (a <= st && dr <= b) {
A[nod].nr = nr; return;
}
int mij = (st + dr) >> 1;
if (a <= mij) update (ns, st, mij, a, b, nr);
if (mij < b) update (nd, mij + 1, dr, a, b, nr);
if (A[ns].nr != -1) A[nod].max = A[ns].nr;
else A[nod].max = A[ns].max;
if (A[nd].nr != -1) A[nod].max = max (A[nod].max, A[nd].nr);
else A[nod].max = max (A[nod].max, A[nd].max);
}
int query (int nod, int st, int dr, int a, int b) {
int nr, x = 0, y = 0, mij = (st + dr) >> 1;
if (a <= st && dr <= b) {
if (A[nod].nr != -1) return A[nod].nr;
else return A[nod].max;
}
if (A[nod].nr != -1) {
nr = A[nod].nr;
A[nod].nr = -1, A[ns].nr = nr, A[nd].nr = nr;
}
if (a <= mij) x = query (ns, st, mij, a, b);
if (mij < b) y = query (nd, mij + 1, dr, a, b);
return max (x, y);
}