#include <bits/stdc++.h>
using namespace std;
int inf =-1e9;
struct Segtree
{
int n;
vector<int>t;
// vector<int>lazy;
void build(vector<int>&a,int x,int lx,int rx)
{
//cout<<x<<" "<<lx<<" "<<rx<<'\n';
if(lx==rx)
{
t[x]=a[lx];
return;
}
int mid=(lx+rx)/2;
build(a,2*x,lx,mid);
build(a,2*x+1,mid+1,rx);
t[x]=max(t[2*x],t[2*x+1]);
}
Segtree(int sz,vector<int>&a)
{
n=sz;
t.assign(4*n,0);
//lazy.assign(4*n,0);
build(a,1,1,n);
}
/*void Push(int x,int lx,int rx)
{
if(lx==rx)
{
t[x]+=lazy[x];
lazy[x]=0;
}
else
{
t[x]+=lazy[x];
lazy[2*x]+=lazy[x];
lazy[2*x+1]+=lazy[x];
lazy[x]=0;
}
}*/
void update(int x,int lx,int rx,int &add, int &q)
{
//cout<<x<<" "<<lx<<" "<<rx<<" "<<lq<<" "<<rq<<'\n';
//Push(x,lx,rx);
if(lx==rx && lx==q)
{
t[x]=add;
//Push(x,lx,rx);
return;
}
if(q<lx || q>rx)
{
return;
}
int mid=(lx+rx)/2;
if(q <= mid) {
update(2*x,lx,mid,add,q);
}else {
update(2*x+1,mid+1,rx,add,q);
}
t[x]=max(t[x*2],t[x*2+1]);
return;
}
int query(int x,int lx,int rx, int lq, int rq)
{
//Push(x,lx,rx);
// cout<<x<<" "<<lx<<" "<<rx<<'\n';
// cout<<lq<<" "<<rq<<'\n';
if(lq<=lx && rq>=rx)
{
return t[x];
}
if(lx>rq || rx<lq)
{
return 0;
}
int mid=(lx+rx)/2,ans=0;
ans=max(query(2*x,lx,mid,lq,rq),query(2*x+1,mid+1,rx,lq,rq));
t[x]=max(t[x*2],t[x*2+1]);
return ans;
}
};
int main()
{
ifstream cin("arbint.in");
ofstream cout("arbint.out");
int n,m;
cin>>n>>m;
vector<int>v(n+1);
for(int i=1;i<=n;i++)
{
cin>>v[i];
}
Segtree h(n,v);
// for(int i=1;i<=n;i++)
//cout << h.query(1, 1, n, i, i) << '\n';
while(m--)
{
int cer;
cin>>cer;
if(cer==0)
{
int a,b;
cin>>a>>b;
// a--;
// b--;
cout<<h.query(1,1,n,a,b)<<'\n';
}
else
{
int a,b;
cin>>a>>b;
//a--;
h.update(1,1,n,b,a);
}
}
return 0;
}