#include <cstdio>
#define maximum(a, b) a > b ? a : b
typedef struct node {
node *left, *right;
int l, r, max;
} node;
using namespace std;
node *root;
int N, M;
node* buildTree(int l, int r) {
node *nod = new node;
nod -> l = l;
nod -> r = r;
nod -> max = 0;
if (l == r)
nod -> left = nod -> right = NULL;
else {
nod -> left = buildTree(l, (l+r) >> 1);
nod -> right = buildTree(((l+r) >> 1) + 1, r);
}
return nod;
}
void insert(node* nod, int pos, int val) {
if(nod -> l != nod -> r) {
if( ((nod -> l + nod -> r) >> 1) < pos )
insert(nod -> right, pos, val);
else
insert(nod -> left , pos, val);
nod -> max = maximum(nod -> right -> max, nod -> left -> max);
} else {
nod -> max = val;
}
}
void read() {
freopen("arbori.in", "r", stdin);
freopen("arbori.out", "w", stdout);
scanf("%i %i", &N, &M);
root = buildTree(0, N - 1);
int x;
for( int i = 0; i < N; i++) {
scanf("%i", &x);
insert(root, i, x);
}
}
void printTree(node *nod) {
if( !nod -> left && !nod -> right )
printf("%i ", nod -> max);
if( nod -> left )
printTree( nod -> left );
if( nod -> right )
printTree( nod -> right );
}
int maxim(node *nod, int a, int b) {
if (a == nod -> l && b == nod -> r)
return nod -> max;
int m = (nod -> l + nod -> r) >> 1;
if ( b <= m )
return maxim( nod -> left, a, b );
if ( a > m )
return maxim( nod -> right, a, b);
return maximum(maxim(nod -> left, a, m), maxim(nod -> right, m + 1, b));
}
void solve() {
int type, a, b;
for(int i = 0; i < M; i++) {
scanf("%i%i%i", &type, &a, &b);
switch(type){
case(0): printf("%i\n", maxim(root, a - 1, b - 1)); break;
case(1): insert(root, a - 1, b); break;
}
}
}
int main() {
read();
solve();
return 0;
}