#include <vector>
#include <fstream>
#include <iostream>
using namespace std;
struct nod{
int stanga;
int dreapta;
int maxim;
};
void populate(vector<nod> &arbore,vector<int> &marcaj,int n,int s,int d){
arbore[n].maxim=0;
arbore[n].stanga=s;
arbore[n].dreapta=d;
if(s<d){
populate(arbore,marcaj,2*n,s,(s+d)/2);
populate(arbore,marcaj,2*n+1,(s+d)/2+1,d);
}else{
marcaj[s]=n;
}
}
void sus(vector<nod> &arbore,int n){
if(n){
arbore[n].maxim=max(arbore[2*n].maxim,arbore[2*n+1].maxim);
sus(arbore,n/2);
}
}
void add(vector<nod> &arbore,int n,int v){
arbore[n].maxim=v;
sus(arbore,n/2);
}
int cauta(vector<nod> &arbore,int n,int a,int b){
if(a<=arbore[n].stanga and b>=arbore[n].dreapta) return arbore[n].maxim;
else{
int maxim=0;
if(a<=(arbore[n].stanga+arbore[n].dreapta)/2){
maxim=max(maxim,cauta(arbore,2*n,a,b));
}
if(b>=(arbore[n].stanga+arbore[n].dreapta)/2+1){
maxim=max(maxim,cauta(arbore,2*n+1,a,b));
}
return maxim;
}
}
int main(){
ifstream in("arbint.in");
ofstream out("arbint.out");
int n,m;in>>n>>m;
vector<int> marcaj(n+1);
vector<nod> arbore(4*n+1);
populate(arbore,marcaj,1,1,n);
for(int i=1;i<=n;i++){
int temp;in>>temp;
add(arbore,marcaj[i],temp);
}
for(int j=0;j<m;j++){
int tip;in>>tip;
int a,b;in>>a>>b;
if(!tip){
out<<cauta(arbore,1,a,b)<<"\n";
}else{
add(arbore,marcaj[a],b);
}
}
}