#include <fstream>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
ifstream fin("arbint.in");
ofstream fout("arbint.out");
vector<int>aint;
vector<int>v;
void resizeAint(int n){
aint.resize(4*n+5);
}
void updateAint(int pozTree,int st,int dr,int pozUpdate,int valUpdate){
if(st==dr){
aint[pozTree]=valUpdate;
return;
}
int leftChild=2*pozTree;
int rightChild=2*pozTree+1;
int mij=(st+dr)/2;
if(pozUpdate<=mij){
updateAint(leftChild, st, mij, pozUpdate,valUpdate);
}else{
updateAint(rightChild, mij+1, dr, pozUpdate,valUpdate);
}
aint[pozTree]=max(aint[leftChild],aint[rightChild]);
}
void buildAint(int pozTree,int st,int dr){
if(st==dr){
aint[pozTree]=v[st-1];
return;
}
int leftChild=2*pozTree;
int rightChild=2*pozTree+1;
int mij=(st+dr)/2;
buildAint(leftChild, st, mij);
buildAint(rightChild, mij+1, dr);
aint[pozTree]=max(aint[leftChild],aint[rightChild]);
}
int queryAint(int pozTree,int st,int dr,int stFind,int drFind){
if(st>=stFind && dr<=drFind){
return aint[pozTree];
}
int leftChild=2*pozTree;
int rightChild=2*pozTree+1;
int mij=(st+dr)/2;
int rightAnswr=0;
int leftAnswr=0;
if(stFind<=mij){
leftAnswr=queryAint(leftChild, st, mij, stFind, drFind);
}
if(drFind>mij){
rightAnswr=queryAint(rightChild, mij+1, dr, stFind, drFind);
}
return max(leftAnswr,rightAnswr);
}
int main(){
int n,q;
fin>>n>>q;
resizeAint(n);
v.resize(n);
for(int i=0;i<n;++i){
fin>>v[i];
}
buildAint(1, 1, n);
int op,st,dr,elem,val;
for(int i=0;i<q;++i){
fin>>op;
if(op==0){
fin>>st>>dr;
fout<<queryAint(1, 1, n, st, dr)<<"\n";
}else{
fin>>elem>>val;
updateAint(1, 1, n, elem, val);
}
}
return 0;
}