#include <iostream>
#include <fstream>
using namespace std;
ifstream fin("arbint.in");
ofstream fout("arbint.out");
int v[100001], maxim[400004];
int create(int nod, int l, int r)
{
if(r==l) //dc suntem in frunza
{
maxim[nod] = v[l];
return v[l];
}
//else -> dc suntem in nod interior
int mid = (l+r)/2; //in caz de overflow: l+(r-l)2;
int val1 = create(2*nod, l, mid);
int val2 = create(2*nod+1, mid+1, r);
//maxim[nod] = val1>val2? val1 : val2; - time limit caca maca
maxim[nod] = max(val1, val2);
return maxim[nod];
}
void update(int nod, int l, int r, int ind, int val)
{
if(r==l)
{
v[l] = val;
maxim[nod]=val;
}
else
{
int mid = l+(r-l)/2;
if(ind <= mid)
update(2*nod, l, mid, ind, val);
else
update(2*nod+1, mid+1, r, ind, val);
//maxim[nod] = maxim[2*nod] > maxim[2*nod+1]? maxim[2*nod] : maxim[2*nod+1];
maxim[nod] = max(maxim[2*nod], maxim[2*nod+1]);
}
}
int query(int nod, int l, int r, int st, int dr)
//l, r capetele intervalului de care este raspunzator nodul
//st, dr capetele intervalului din cerinta
{
if(l>=st && r<=dr)
return maxim[nod];
else
if(r<st || l>dr)
return 0;
//else
int mid = (l+r)/2;
int val1 = query(2*nod, l, mid, st, dr);
int val2 = query(2*nod +1, mid+1, r, st, dr);
//return val1>val2? val1: val2;
return max(val1, val2);
}
int main()
{
int n, m, op, a, b, i;
fin>>n>>m;
for(i=1; i<=n; i++)
fin>>v[i];
create(1, 1, n);
for(i=1; i<=m; i++)
{
fin>>op>>a>>b;
if(op==0)
fout<<query(1, 1, n, a, b)<<'\n';
else
update(1, 1, n, a, b);
}
}