#include <fstream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#define NMAX 100005
#define INF 0x3f3f3f3f
#define get_max(a,b) ((a)>(b)?(a):(b))
#define get_min(a,b) ((a)<(b)?(a):(b))
using namespace std;
ifstream in ( "arbint.in" );
ofstream out ( "arbint.out" );
int Answer = -INF;
int N , M;
int AINT [ 4*NMAX ];
void Update ( int Node , int Left , int Position , int Right , int value ){
if ( Left == Right ){
AINT[Node] = value ;
return ;
}
int Middle = ( Left + Right ) / 2;
if ( Position < Middle )
Update ( 2* Node ,Left , Position , Middle , value );
else Update ( 2*Node + 1 , Middle +1, Position , Right , value );
AINT[Node] = get_max( AINT[2*Node] , AINT [ 2*Node + 1] );
}
void Query ( int Node , int Left , int Right , int SearchLeft , int SearchRight ){
if ( Left >= SearchLeft and SearchRight >= Right )
{
Answer = get_max( Answer , AINT[Node]);
return;
}
int Middle = ( Left + Right ) / 2;
if ( Middle >= SearchLeft )
Query ( 2*Node , Left , Middle , SearchLeft , SearchRight );
if ( Middle < SearchRight )
Query( 2*Node+1 , Middle +1 , Right , SearchLeft, SearchRight);
}
void Read ( void ){
int i , j , value , type , A , B ;
in >> N >> M ;
for ( i = 1 ; i <= N ; ++i )
{
in >> value ;
Update ( 1 , 1 , i , N ,value );
}
for ( i = 1 ; i <= M ; ++i ) {
in >> type >> A >> B ;
if ( type == 1 )
Update ( 1 , 1 , A , N , B) ;
else {
Query (1 , 1 , N , A , B ) ;
out << Answer << "\n";
Answer = - INF ;
}
}
return ;
}
int main ( void ){
Read();
return 0;
}