#include <fstream>
using namespace std;
#define in "arbint.in"
#define out "arbint.out"
const int INF = (1<<30);
template<typename T>
T maxim( T a, T b) { return ((a)>(b)?(a):(b)); }
int getSize(int N) { int i; for ( i = 31; i >= 0 && !(N&(1<<i)); --i ); return ((1<<(i+1))+1); }
void Update( int nod, int left, int right, int poz, int *Tree, int value )
{
if ( left == right )
{
*(Tree+nod) = value;
return;
}
int div = (left+((right-left)>>1));
if ( poz <= div ) Update ( 2*nod, left, div, poz, Tree, value );
else Update ( 2*nod+1, div+1, right, poz, Tree, value );
*(Tree+nod) = maxim(*(Tree+(nod<<1)),*(Tree+(nod<<1)+1));
}
void Query( int nod, int left, int right, int start, int finish, int *Tree, int & mem )
{
if ( start <= left && right <= finish )
{
mem = maxim ( mem, *(Tree+nod) );
return;
}
int div = (left+((right-left)>>1));
if ( start <= div ) Query ( 2*nod, left, div, start, finish, Tree, mem );
if ( finish > div ) Query ( 2*nod+1, div+1, right, start, finish, Tree, mem );
}
int main(void)
{
freopen ( in, "r", stdin );
freopen ( out, "w", stdout );
int N, M, X, op, l, r, SOL,i;
scanf( "%d%d", &N, &M );
int *A = (int*) calloc (getSize((N<<1)+1),sizeof(int));
for ( i = 1; i <= N; ++i )
{
scanf( "%d", &X );
Update( 1, 1, N, i, A, X );
}
for ( ; M; --M )
{
scanf ( "%d%d%d", &op, &l, &r );
if ( op ) Update ( 1, 1, N, l, A, r );
else {
SOL = -INF;
Query(1,1,N,l,r,A,SOL);
printf ( "%d\n", SOL );
}
}
return 0;
}