#include <iostream>
#include <stdio.h>
#define NMAX 100000
using namespace std;
int aint[2*NMAX];
int v[NMAX];
inline int mid( int l, int r ) { return ( l + r ) / 2; }
inline int leftSon( int node ) { return node + 1; }
inline int rightSon( int node, int m, int l ) { return node + 2 * ( m - l + 1 ); }
void build( int node, int l, int r ) {
if( l == r ) {
aint[node] = v[l];
return;
}
int m = mid( l, r );
int lson = leftSon( node );
int rson = rightSon( node, m, l );
build( lson, l, m );
build( rson, m + 1, r );
aint[node] = max( aint[lson], aint[rson] );
}
void update( int node, int l, int r, int pos, int val ) {
if( l == r ) {
aint[node] = val;
return;
}
int m = mid( l, r );
int lson = leftSon( node );
int rson = rightSon( node, m, l );
if( pos <= m )
update( lson, l, m, pos, val );
else
update( rson, m + 1, r, pos, val );
aint[node] = max( aint[lson], aint[rson] );
}
int query( int node, int l, int r, int a, int b ) {
if( a <= l && r <= b )
return aint[node];
int m = mid( l, r );
int lson = leftSon( node );
int rson = rightSon( node, m, l );
int res = 0;
if( a <= m )
res = max( res, query( lson, l, m, a, b ) );
if( m < b )
res = max( res, query( rson, m + 1, r, a, b ) );
return res;
}
int main() {
FILE *fin, *fout;
int n, m, i, type, a, b, pos, val;
fin = fopen( "arbint.in", "r" );
fout = fopen( "arbint.out", "w" );
fscanf( fin, "%d%d", &n, &m );
for( i = 0; i < n; i++ )
fscanf( fin, "%d", &v[i] );
build( 0, 0, n - 1 );
for( ; m; m-- ) {
fscanf( fin, "%d", &type );
if( type == 0 ) {
fscanf( fin, "%d%d", &a, &b );
a--, b--;
fprintf( fout, "%d\n", query( 0, 0, n - 1, a, b ) );
}
else {
fscanf( fin, "%d%d", &pos, &val );
pos--;
v[pos] = val;
update( 0, 0, n - 1, pos, val );
}
}
fclose( fin );
fclose( fout );
return 0;
}