#include <fstream>
#include <vector>
using namespace std;
ifstream in ("arbint.in");
ofstream out ("arbint.out");
class maxSegmentTree{
int *data;
int size;
int n;
void createVal(int left,int right,int position,vector<int> & v){ // function used by a constructor
if(left==right){ // current node hold the number from v with index left
data[position]=v[left-1]; // this is cleary its maximum
return;
}
createVal(left,(left+right)/2,2*position,v); // we explore the left interval,mid interval
createVal((left+right)/2+1,right,2*position+1,v); // we explore the mid+1,right interval
data[position]=max(data[2*position],data[2*position+1]); // we set the maximum on the current interval based on previous explorations
}
int getMax(int left,int right,int a,int b,int position){ // we will find the maximum in the [a,b]
int result=-1;
int mid=(left+right)/2;
if(left>=a&&right<=b)
return data[position];
if(mid<b){
result=max(result,getMax(mid+1,right,a,b,2*position+1));
}
if(mid>=a){
result=max(result,getMax(left,mid,a,b,2*position));
}
return result;
}
bool updateVal(int left,int right,int position,int index,int val){
int mid=(left+right)/2;
if(left==right && left==index){
data[position]=val;
return true;
}
if(mid>=index){
updateVal(left,mid,2*position,index,val);
}
else{
updateVal(mid+1,right,2*position+1,index,val);
}
data[position]=max(data[2*position],data[2*position+1]);
}
public:
maxSegmentTree(int x){
n=x;
int log,aux;
//for(aux=1;aux<=n;aux<<=1,log++);
//log--;
log=8;
data=new int[n*log];
for(int i=1;i<n*log;++i){
data[i]=-1;
}
}
maxSegmentTree(vector<int> & v){
n=v.size();
int log=8;
data=new int[n*log];
createVal(1,n,1,v);
}
int query(int l,int r){
return getMax(1,n,l,r,1);
}
bool update(int position,int value){
return updateVal(1,n,1,position,value);
}
};
int main(){
int n,m;
maxSegmentTree *st;
vector<int> v;
in>>n>>m;
int op,a,b;
for(int i=1;i<=n;++i){
in>>a;
v.push_back(a);
}
st=new maxSegmentTree(v);
for(int i=1;i<=m;++i){
in>>op>>a>>b;
if(op==0){
out<<st->query(a,b)<<"\n";
continue;
}
st->update(a,b);
}
return 0;
}