#include <iostream>
#include <fstream>
#include <algorithm>
#include <climits>
using namespace std;
void build(int a[], int tree[], int start, int stop, int node)
{
if(start==stop)
{
tree[node]=a[start];
}
else
{
int m=(start+stop)/2;
build(a,tree,start,m,2*node);
build(a,tree,m+1,stop,2*node+1);
tree[node]=max(tree[2*node],tree[2*node+1]);
}
}
int query(int tree[], int node, int start, int stop, int l, int r)
{
if(stop<l || r<start)
return INT_MIN;
if(l<=start && stop<=r)
return tree[node];
int m=(start+stop)/2;
int m1=query(tree,2*node,start,m,l,r);
int m2=query(tree,2*node+1,m+1,stop,l,r);
return max(m1,m2);
}
void update(int tree[], int a[],int node, int start, int stop, int idx, int val)
{
if(start==stop)
{
a[idx]=val;
tree[node]=val;
}
else
{
int m=(start+stop)/2;
if(start<=idx && idx<=m)
update(tree,a,2*node,start,m,idx,val);
else
update(tree,a,2*node+1,m+1,stop,idx,val);
tree[node]=max(tree[2*node],tree[2*node+1]);
}
}
int main()
{
ifstream in("arbint.in");
ofstream out("arbint.out");
int n, nr, a[100001],tree[200010];
in>>n>>nr;
for(int i=1; i<=n; i++)
in>>a[i];
build(a,tree,1,n,1);
int x, y,opt;
for(int i=1; i<=nr; i++)
{
in>>opt>>x>>y;
switch(opt)
{
case 0:
{
out<<query(tree,1,1,n,x,y)<<"\n";
break;
}
case 1:
{
update(tree,a,1,1,n,x,y);
break;
}
}
}
return 0;
}