#include<iostream>
#include<fstream>
#include<vector>
#define MIN_VAL -100
using namespace std;
int n,m;
std::vector<int> arr;
std::vector<int> vec;
void construct_segment_tree(int x,int y,int pos)
{
if(x == y) arr[pos] = vec[x];
else
{
construct_segment_tree(x,(x+y)/2,2*pos+1);
construct_segment_tree(((x+y)/2)+1,y,2*pos+2);
arr[pos] = max(arr[2*pos+1],arr[2*pos+2]);
}
}
int range_query(int x,int y,int pos,int x1,int y1)
{
if(x >= x1 && y <= y1) return arr[pos];
if(x > y1 || y < x1) return MIN_VAL;
return max(range_query(x,(x+y)/2,2*pos+1,x1,y1),range_query(((x+y)/2)+1,y,2*pos+2,x1,y1));
}
int main()
{
freopen("arbint.in","r",stdin);
freopen("arbint.out","w",stdout);
scanf("%d%d",&n,&m);
arr.assign(2*n,0);
int k1;
for(int i=0;i<n;i++)
{
scanf("%d",&k1);
vec.push_back(k1);
}
construct_segment_tree(0,vec.size()-1,0);
bool reconstruct = false;
for(int i=0;i<m;i++)
{
int k2,k3;
scanf("%d%d%d",&k1,&k2,&k3);
if(k1 == 0)
{
if(reconstruct == true)
{
construct_segment_tree(0,vec.size()-1,0);
reconstruct = false;
}
printf("%d\n",range_query(0,vec.size()-1,0,k2-1,k3-1));
}
else if(k1 == 1)
{
vec[k2-1] = k3;
reconstruct = true;
}
}
}