#include<stdio.h>
#include<stdlib.h>
int ArbInt[100000];
int v[100000];
int max (int a, int b) {
if (a < b)
return b;
else
return a;
}
int build (int nod, int l, int r) {
if (l == r) {
ArbInt[nod] = v[l];
return v[l];
}
int m = (l + r) >> 1;
int p1 = build (nod * 2 + 1, l, m);
int p2 = build (nod * 2 + 2, m + 1, r);
ArbInt[nod] = max (p1, p2);
return ArbInt[nod];
}
int inclus (int a, int b, int l, int r) {
if (a <= l && r <= b)
return 1;
else
return 0;
}
int intersect (int a, int b, int l, int r) {
if (a <= r && l <= b)
return 1;
else
return 0;
}
int query (int nod, int l, int r, int a, int b) {
if (inclus (a, b, l, r))
return ArbInt[nod];
int m = (l + r) >> 1;
int q1 = -1;
int q2 = -1;
if (intersect (a, b, l, m))
q1 = query (nod * 2 + 1, l, m, a, b);
if (intersect (a, b, m + 1, r))
q2 = query (nod * 2 + 2, m + 1, r, a, b);
return max (q1, q2);
}
int update (int nod, int l, int r, int a, int b, int val) {
if (inclus (a, b, l, r)) {
ArbInt[nod] = val;
return val;
}
int m = (l + r) >> 1;
if (intersect (a, b, l, m))
update (nod * 2 + 1, l, m, a, b, val);
if (intersect (a, b, m + 1, r))
update (nod * 2 + 2, m + 1, r, a, b, val);
ArbInt[nod] = max (ArbInt[nod * 2 + 1], ArbInt[nod * 2 + 2]);
return ArbInt[nod];
}
int main(int argc, char *argv[]) {
freopen ("date.in", "r", stdin);
int n, m;
scanf ("%d%d", &n, &m);
int i;
for (i = 0; i < n; ++i)
scanf ("%d", &v[i]);
build (0, 0, n - 1);
for (i = 0; i < m; ++i) {
int o, l, r;
scanf ("%d%d%d", &o, &l, &r);
if (o == 0)
printf ("%d\n", query (0, 0, n - 1, l - 1, r - 1));
else if (o == 1)
update (0, 0, n - 1, l - 1, l - 1, r);
}
return 0;
}