#include <fstream>
#include <algorithm>
using namespace std;
#define INF (2000000000)
ifstream in("arbint.in");
ofstream out("arbint.out");
int arb[202500],i,j,x[100500],n,m,op, a,b, maxim;
void make_tree(int nod, int st, int dr)
{
if(st == dr)
arb[nod] = x[st];
else if(st<dr)
{
make_tree(2*nod, st, (st+dr)/2);
make_tree(2*nod+1, (st+dr)/2+1, dr);
arb[nod] = max(arb[2*nod], arb[2*nod+1]);
}
}
void update(int nod, int st, int dr, int pos)
{
if(st == dr && st == pos)
arb[nod] = x[pos];
else if(st <= pos && pos <= dr)
{
if((st+dr)/2 <= pos)
update(2*nod, st, (st+dr)/2, pos);
if((st+dr)/2+1 >= pos)
update(2*nod+1, (st+dr)/2+1, dr, pos);
arb[nod] = max(arb[2*nod], arb[2*nod+1]);
}
}
void query(int nod, int ist, int idr, int st, int dr)
{
if(st>dr)
return;
if(st >= ist && dr <= idr)
{
if(maxim < arb[nod])
maxim = arb[nod];
return;
}
else if(idr < st || ist > dr)
return;
else
{
if(ist <= (st+dr)/2)
query(2*nod, ist, idr, st, (st+dr)/2);
if(idr >= (st+dr)/2+1)
query(2*nod+1, ist, idr, (st+dr)/2+1, dr);
//return max(query(2*nod, ist, idr, st, (st+dr)/2), query(2*nod+1, ist,
// idr, (st+dr)/2+1, dr));
}
}
int main()
{
in>>n>>m;
for(i=1; i<=n; i++)
in>>x[i];
make_tree(1,1,n);
for(i=1; i<=m; i++)
{
in>>op>>a>>b;
if(op == 0)
maxim=-INF,query(1, a, b, 1, n), out<<maxim<<'\n';
else
x[a] = b, update(1, 1, n, a);
}
return 0;
}