#include <bits/stdc++.h>
FILE *in = fopen("arbint.in", "r"), *out = fopen("arbint.out", "w") ;
const int MV = 1e5 ;
int aint[MV << 2] ;
int v[MV + 5] ;
int n, m ;
void build(int node, int st, int dr) {
if (st == dr) {
aint[node] = v[st] ;
return ;
}
int mij((st + dr) >> 1) ;
build((node << 1), st, mij) ;
build((node << 1) + 1, mij + 1, dr) ;
aint[node] = std::max(aint[node << 1], aint[(node << 1) + 1]) ;
}
void update(int node, int st, int dr, int x, int y) {
if (st == x && dr == x) {
aint[node] = y ;
return ;
}
int mij((st + dr) >> 1) ;
if (x <= mij) {
update(node << 1, st, mij, x, y) ;
} else {
update((node << 1) + 1, mij + 1, dr, x, y) ;
}
aint[node] = std::max(aint[node << 1], aint[(node << 1) + 1]) ;
}
int querry(int node, int st, int dr, int x, int y) {
if (st == x && dr == y) {
return aint[node] ;
}
int mij((st + dr) >> 1) ;
if (y <= mij) {
return querry(node << 1, st, mij, x, y) ;
} else if (mij < x) {
return querry((node << 1) + 1, mij + 1, dr, x, y) ;
}
int left = querry(node << 1, st, mij, x, mij) ;
int right = querry((node << 1) + 1, mij + 1, dr, mij + 1, y) ;
return std::max(left, right) ;
}
int main() {
fscanf(in, "%d %d", &n, &m) ;
for (int i = 1 ; i <= n ; ++ i) {
fscanf(in, "%d ", v + i) ;
}
build(1, 1, n) ;
int type, a, b ;
while (m --) {
fscanf(in, "%d %d %d\n", &type, &a, &b) ;
if (type == 0) {
fprintf(out, "%d\n", querry(1, 1, n, a, b)) ;
} else update(1, 1, n, a, b) ;
}
}