#include <fstream>
using namespace std;
ifstream fin("arbint.in");
ofstream fout("arbint.out");
int x,arb[1000001],n,m;
void actualizare(int nod,int st,int dr,int poz,int val)
{
/// va trebui sa simulam atribuirea a[poz]=val
/// determinam intervalul elementar in care st=dr=poz
/// adica determin nod
/// plus actualizarea nodurilor din arbore pe traseul in sus pana la radacina
/// fiecare componenta arb[nod] va tine maximul valorilor pentru
/// valorile componentelor vectorului cu indici din [st, dr]
int mij;
if(st==dr)
arb[nod]=val;
else
{
mij=(st+dr)/2;
if(poz<=mij)
actualizare(2*nod,st,mij,poz,val);
else
actualizare(2*nod+1,mij+1,dr,poz,val);
arb[nod]=max(arb[2*nod],arb[2*nod+1]);
}
}
int interogare(int nod,int st,int dr,int a,int b)
{
/// determin valoarea maxima pe intervalul dat [a,b]
int mij,rez1,rez2,rez;
if(dr<a||b<st)
return -1;
if(a<=st && dr<=b)///intervalul [st,dr] este inclus in [a,b]
return arb[nod];
mij=(st+dr)/2;
rez1=interogare(2*nod,st,mij,a,b);
rez2=interogare(2*nod+1,mij+1,dr,a,b);
rez=max(rez1,rez2);
return rez;
}
int main()
{
int tip,a,b,i;
fin>>n>>m;
for(i=1; i<=n; i++)
{
fin>>x;///x[i];
actualizare(1,1,n,i,x);/// nod=1, st=1, dr=n, poz=i, val=x[i]
}
for(i=1; i<=m; i++)
{
fin>>tip>>a>>b;
if(tip==1)
actualizare(1,1,n,a,b);///nod, [st dr], poz, val
else
fout<<interogare(1,1,n,a,b)<<'\n';///nod, st, dr, [a b]
}
return 0;
}