#include <iostream>
#include <cstdio>
using namespace std;
const int MAXN = 100000;
int segTree[2*MAXN+1], N, M;
void update(int nod, int left, int right, int poz, int value)
{
if( left == right )
segTree[ nod ] = value;
else
{
int m = (left + right)/2;
if( poz <= m /*&& 2*nod <= 2*N - 1*/ )
update( 2*nod, left, m, poz, value );
if( poz > m /*&& 2*nod + 1 <= 2*N - 1*/ )
update( 2*nod + 1, m + 1, right, poz, value );
int maxLeft = -1, maxRight = -1;
//if( 2*nod <= 2*N - 1 )
maxLeft = segTree[ 2*nod ];
//if( 2*nod + 1 <= 2*N - 1 )
maxRight = segTree[ 2*nod + 1 ];
//if( maxLeft != -1 || maxRight != -1 )
segTree[ nod ] = max( maxLeft, maxRight );
}
}
//max dintre a si b
int maxim = -1;
void querry(int nod, int left, int right, int a, int b)
{
if( a <= left && right <= b )
maxim = max( maxim, segTree[ nod ] );
else
{
int m = (left + right)/2;
if( a <= m /*&& 2*nod <= 2*N - 1*/ )
querry( 2*nod, left, m, a, b );
if( m < b /*&& 2*nod + 1 <= 2*N - 1*/ )
querry( 2*nod + 1, m + 1, right, a, b);
}
}
int v[MAXN+1];
int sQuerry(int a, int b)
{
int maxim = -1;
for(int i = a; i <= b; i++)
maxim = max( maxim, v[ i ] );
return maxim;
}
void citire()
{
scanf("%d %d",&N, &M);
for(int i = 1; i <= N; i++)
{
int x; scanf("%d",&x);
update(1,1,N,i,x);
v[ i ] = x;
}
}
int main()
{
freopen("arbint.in","r",stdin);
freopen("arbint.out","w",stdout);
citire();
for(int i = 1; i <= M; i++)
{
int cod, a, b; scanf("%d %d %d",&cod,&a,&b);
if( cod == 0 )
{
maxim = -1;
querry(1, 1, N, a, b);
printf("%d\n",maxim);
//printf("%d\n",sQuerry(a,b));
}
else
{
update(1, 1, N, a, b);
//v[ a ] = b;
}
}
return 0;
}