#include <iostream>
#include <fstream>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <cctype>
#include <unordered_map>
#include <cmath>
#include <bitset>
#include <set>
#include <string>
#include <cstring>
#include <algorithm>
#include <deque>
using namespace std;
ifstream in("arbint.in");
ofstream out("arbint.out");
int a[100005],b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,S,t,x,y,z,ok,nr,C,v,xc,yc,Min,w,poz;
struct Tree{
Tree *left_son;
Tree *right_son;
int info;
};
Tree *T;
void Init(int node,Tree *&T,int *a,int left,int right){
if(left==right){
T->info=a[++k];
}
else{
int mid=(left+right)/2;
T->left_son=(Tree *) malloc(sizeof(Tree));
T->right_son=(Tree *) malloc(sizeof(Tree));
Init(2*node,T->left_son,a,left,mid);
Init(2*node+1,T->right_son,a,mid+1,right);
T->info=max(T->left_son->info,T->right_son->info);
}
}
void Update(int node,Tree *&T,int pos,int value,int left,int right){
if(left==right){
T->info=value;
}
else{
int mid=(left+right)/2;
if(pos<=mid) {Update(2*node,T->left_son,pos,value,left,mid);}
else{
Update(2*node+1,T->right_son,pos,value,mid+1,right);
}
T->info=max(T->left_son->info,T->right_son->info);
}
}
int Query(int node,Tree *T,int left_q,int right_q,int left,int right){
if(left_q<=left && right<=right_q){
return T->info;
}
else{
int mid=(left+right)/2;
int Max=-1;
if(left_q<=mid) {
Max=max(Max,Query(2*node,T->left_son,left_q,right_q,left,mid));
}
if(right_q>=mid+1){
Max=max(Max,Query(2*node+1,T->right_son,left_q,right_q,mid+1,right));
}
return Max;
}
}
int main()
{
in>>n>>m;
for(i=1;i<=n;i++){
in>>a[i];
}
Tree *T=new Tree;
k=0;
Init(1,T,a,1,n);
for(i=1;i<=m;i++){
in>>t>>x>>y;
if(t==1){
Update(1,T,x,y,1,n);
}
if(t==0){
out<<Query(1,T,x,y,1,n)<<'\n';
}
}
return 0;
}