//#pragma GCC optimize ("O3")
//#pragma GCC target ("sse4")
#include <bits/stdc++.h>
using namespace std;
ifstream fin("arbint.in");
ofstream fout("arbint.out");
static const int NMAX = 1e5+5;
int aint[NMAX*4];
int v[NMAX];
int n,m;
void build(int nod, int st, int dr)
{
if(st == dr){
aint[nod] = v[st];
return;
}
int mid = st + (dr-st)/2;
build(nod*2,st,mid);
build(nod*2+1,mid+1,dr);
aint[nod]= max(aint[nod*2],aint[nod*2+1]);
}
void update(int nod, int st, int dr, int pos, int newValue)
{
if(st == dr)
{
v[st] = newValue;
aint[nod] = newValue;
return;
}
int mid = st + (dr-st)/2;
if(pos<= mid)
update(nod*2,st,mid,pos,newValue);
else
update(nod*2+1,mid+1,dr,pos,newValue);
aint[nod] = max(aint[nod*2],aint[nod*2+1]);
}
int query(int nod,int st, int dr, int a, int b)
{
if(st == dr || (st >= a && dr <= b))
{
return aint[nod];
}
int mid = st + (dr-st)/2;
if(a <= mid && b >= mid+1)
{
return max(query(nod*2,st,mid,a,b),query(nod*2+1,mid+1,dr,a,b));
}
if(a <= mid)
{
return query(nod*2,st,mid,a,b);
}
else if(b >= mid+1)
{
return query(nod*2+1,mid+1,dr,a,b);
}
}
int main()
{
fin >> n >> m;
for(int i =1; i<= n; ++i)
fin >> v[i];
build(1,1,n);
for(int i = 1; i<= m; ++i)
{
int op;fin >> op;
int a,b;
fin >> a >> b;
if(op == 0)
{
fout << query(1,1,n,a,b) << '\n';
}
else
{
update(1,1,n,a,b);
}
}
return 0;
}