#include <bits/stdc++.h>
#define nmax 263000
using namespace std;
FILE *fin=fopen("arbint.in","r");
FILE *fout=fopen("arbint.out","w");
int n,interogari,arbore[nmax];
void update(int nod_curent,int pozitie,int valoare,int st,int dr)///nod_curent->nodul la care suntem in arbore;modificam elem de pe 'pozitie'(vector initial) cu 'valoare';intervalul_curent e 'st'-'dr';
{
if(st==dr)///suntem la frunza
{
arbore[nod_curent]=valoare;
}
else
{
int mijloc=(st+dr)/2;
if(pozitie<=mijloc)
{
update(nod_curent*2,pozitie,valoare,st,mijloc);
}
else if(pozitie>mijloc)
{
update(nod_curent*2+1,pozitie,valoare,mijloc+1,dr);
}
arbore[nod_curent]=max(arbore[nod_curent*2],arbore[nod_curent*2+1]);
}
}
int query(int nod_curent,int a,int b,int st,int dr)///[a,b] -> intervalul in care se cere maximul
{
if(a<=st&&dr<=b)
{
return arbore[nod_curent];
}
else
{
int mijloc=(st+dr)/2;
int val1=0,val2=0;
if(a<=mijloc)
{
val1=query(nod_curent*2,a,b,st,mijloc);
}
if(b>mijloc)
{
val2=query(nod_curent*2+1,a,b,mijloc+1,dr);
}
return max(val1,val2);
}
}
int main()
{
int varf,cerinta,a,b;
fscanf(fin,"%d %d",&n,&interogari);
for(int i=1;i<=n;i++)
{
fscanf(fin,"%d",&varf);
update(1,i,varf,1,n);
}
for(int i=1;i<=interogari;i++)
{
fscanf(fin,"%d %d %d",&cerinta,&a,&b);
if(cerinta==1)
{
update(1,a,b,1,n);
}
else
{
varf=query(1,a,b,1,n);
fprintf(fout,"%d\n",varf);
}
}
fclose(fin);
fclose(fout);
return 0;
}