#include <iostream>
#include <stdio.h>
using namespace std;
const int N=100000;
int marb[N],v[N];
int maxim, n, m,cnt=1, sol[N];
int Maxim(int x, int y){
if(x>y) return x;
else return y;
}
void afisare(){
FILE *out;
out=fopen("arbint.out","w");
for(int i=1;i<cnt;i++)
fprintf(out,"%d\n",sol[i]);
}
void query(int inceput, int sfarsit, int nod, int st, int dr){
int mij=(st+dr)/2;
if(inceput<=st&&sfarsit>=dr){
if(maxim<marb[nod]) maxim=marb[nod];
return;
}
if(inceput<= mij) query(inceput , sfarsit, 2*nod,st,mij);
if(mij<sfarsit) query(inceput, sfarsit, 2*nod+1,mij+1,dr);
}
void schimba(int elem, int poz,int nod, int st, int dr){
int mij=(st+dr)/2;
if(st==dr){
marb[nod]=elem;
return;
}
if (poz<=mij) schimba(elem, poz, 2*nod, st, mij);
else schimba(elem, poz, 2*nod+1,mij+1,dr );
marb[nod]=Maxim(marb[2*nod], marb[2*nod+1] );
}
void citire(){
FILE *in;
in=fopen("arbint.in","r");
fscanf(in,"%d%d", &n, &m);
int a,b,c;
for(int i=1;i<=n;i++) fscanf(in,"%d",&v[i]);
for(int i=1;i<=n;i++) schimba(v[i],i,1,1,n);//inserez elem v[i] pe pozitia i incepand de la nodul unu dintre intervalul 1 si n
for(int i=1;i<=m;i++){
fscanf(in,"%d%d%d",&c,&a,&b);
if(c==1) schimba(b,a,1,1,n);
else {
maxim=-1;
query(a,b,1,1,n);// aflu maximul intre nodul a si b de la nodul 1 in arborele de la 1 la n
sol[cnt++]=maxim;
}
}
}
int main()
{
citire();
afisare();
return 0;
}