#include<cstdio>
#include<algorithm>
using std::max;
struct node {
int v;
node *s, *d;
} *roots[100005];
int v[270000], rn;
void update(node *nd, int l, int r, int a, int b, int v){
int m = (l + r) / 2;
if(l == r) {
nd->v = v;
return;
} else if(b <= m) {
nd->s = new node(*nd->s);
update(nd->s, l, m, a, b, v);
} else if(m + 1 <= a) {
nd->d = new node(*nd->d);
update(nd->d, m+1, r, a, b, v);
} else {
nd->s = new node(*nd->s);
nd->d = new node(*nd->d);
update(nd->s, l, m, a, m, v);
update(nd->d, m+1, r, m+1, b, v);
}
nd->v = max(nd->s->v, nd->d->v);
}
int query(node *nd, int l, int r, int a, int b){
int m = (l + r) / 2;
if(l == a && r == b)
return nd->v;
else if(b <= m)
return query(nd->s, l, m, a, b);
else if(m + 1 <= a)
return query(nd->d, m+1, r, a, b);
else
return std::max(query(nd->s, l, m, a, m), query(nd->d, m+1, r, m+1, b));
}
void build(node *nd, int l, int r){
int m = (l + r) / 2;
if(l == r)
nd->v = v[l];
else {
nd->s = new node;
nd->d = new node;
build(nd->s, l, m);
build(nd->d, m+1, r);
nd->v = std::max(nd->s->v, nd->d->v);
}
}
int main(void){
freopen("arbint.in", "r", stdin);
#ifdef INFOARENA
freopen("arbint.out", "w", stdout);
#endif
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1 ; i <= n ; i++)
scanf("%d", v + i);
roots[0] = new node;
build(roots[0], 0, n);
while(m--){
int op, a, b;
scanf("%d%d%d", &op, &a, &b);
if(op){
roots[rn+1] = new node(*roots[rn]);
update(roots[++rn], 0, n, a, a, b);
} else
printf("%d\n", query(roots[rn], 0, n, a, b));
}
}