#include <cstdio>
#include <algorithm>
using namespace std;
#define NMAX 100000
#define INFI 0x3f3f3f3f
int Arbore[ NMAX * 4 ];
void Update ( int target, int poz, int st, int dr, int val );
int Querry ( int poz, int start, int finish, int st, int dr );
int main () {
freopen( "arbint.in", "r", stdin );
freopen( "arbint.out", "w", stdout );
int n, m, i, j, x, y, t;
scanf( "%d%d",&n,&m );
for ( i = 1; i <= n; ++i ) {
scanf( "%d",&x );
Update( i, 1, 1, n, x );
}
while ( m-- ) {
scanf( "%d%d%d",&t,&x,&y );
if ( t == 0 ) {
printf( "%d\n", Querry( 1, x, y, 1, n ) );
} else {
Update( x, 1, 1, n, y );
}
}
return 0;
}
void Update ( int target, int poz, int st, int dr, int val ) {
int mid = ( st + dr ) / 2;
if ( st == dr ) {
Arbore[ poz ] = val;
return ;
}
if ( target <= mid ) Update( target, poz * 2, st, mid, val );
else Update( target, poz * 2 + 1, mid + 1, dr, val );
Arbore[ poz ] = max( Arbore[ poz * 2 ] , Arbore[ poz * 2 + 1 ] );
}
int Querry ( int poz, int start, int finish, int st, int dr ) {
if ( start <= st && dr <= finish ) {
return Arbore[ poz ];
}
int mid = ( st + dr ) / 2;
int a, b; a = b = -INFI;
if ( start <= mid ) a = Querry( poz * 2, start, finish, st, mid );
if ( mid < finish ) b = Querry( poz * 2 + 1, start, finish, mid + 1, dr );
return max( a, b );
}