#include <fstream>
using namespace std;
#define in "arbint.in"
#define out "arbint.out"
const int INF = (1<<30);
int SOL, X, VALUE;
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 )
{
if ( left == right )
{
*(Tree+nod) = VALUE;
return;
}
int div = (left+((right-left)>>1));
if ( poz <= div ) Update ( 2*nod, left, div, poz, Tree );
else Update ( 2*nod+1, div+1, right, poz, Tree );
*(Tree+nod) = maxim(*(Tree+(nod<<1)),*(Tree+(nod<<1)+1));
}
void Query( int nod, int left, int right, int start, int finish, int *Tree )
{
if ( start <= left && right <= finish )
{
SOL = maxim( SOL, *(Tree+nod) );
return;
}
int div = (left+((right-left)>>1));
if ( start <= div ) Query ( 2*nod, left, div, start, finish, Tree );
if ( finish > div ) Query ( 2*nod+1, div+1, right, start, finish, Tree );
}
int main(void)
{
freopen ( in, "r", stdin );
freopen ( out, "w", stdout );
int N, M, op, l, r, 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 );
VALUE = X;
Update( 1, 1, N, i, A );
}
for ( ; M; --M )
{
scanf ( "%d%d%d", &op, &l, &r );
VALUE = r;
if ( op ) Update ( 1, 1, N, l, A );
else {
SOL = -INF;
Query( 1, 1, N, l, r, A );
printf ( "%d\n", SOL );
}
}
return 0;
}