#include <bits/stdc++.h>
using namespace std;
ifstream f("arbint.in");
ofstream g("arbint.out");
const int N=1<<18;
int n,m,p,A[N];
void buildAint()
{
for(int i=1;i<=n;i++)
f>>A[i+p-1];
for(int i=p-1;i>=1;i--)
A[i]=max(A[2*i],A[2*i+1]);
}
int getMax(int nod,int sa,int da,int sq,int dq)
{
/// [sa,da] disjunct de [sq,dq] - returnez 0
if(sa>dq||sq>da)
return 0;
/// [sa,da] inclus [sq,dq] - returnez A[nod]
if(sq<=sa&&da<=dq)
return A[nod];
/// altfel - iau max din prima si adoua jumatate
/// returnez maximul intre cele doua valori
int fiuSt=2*nod;
int fiuDr=2*nod+1;
int mi=(sa+da)/2;
return max(getMax(fiuSt,sa,mi,sq,dq),getMax(fiuDr,mi+1,da,sq,dq));
}
void update(int nod,int val)
{
nod=nod+p-1;
A[nod]=val;
nod/=2;/// incep din "tatal" nodului modificat
while(nod>0)
{
int fiuSt=2*nod;
int fiuDr=2*nod+1;
A[nod]=max(A[fiuSt],A[fiuDr]);///recalculez valoarea
nod/=2;///merg la tata
}
}
int main()
{
f>>n>>m;
p=1;
while(p<n)p*=2;
buildAint();
for(;m;m--)
{
int tip,a,b;
f>>tip>>a>>b;
if(tip==0)
g<<getMax(1,1,p,a,b)<<'\n';
else
update(a,b);
}
return 0;
}
//5 5
//4 3 5 6 1
//0 1 3
//1 3 2
//0 2 3
//1 4 2
//0 1 5
// <0>
// 8< 1>
// [1,8]
// 8< 2> 1< 3>
// [1,4] [5,8]
// 4< 4> 8< 5> 1< 6> 0< 7>
// [1,2] [3,4] [5,6] [7,8]
// 4< 8> 3< 9> 2<10> 8<11> 1<12> 0<13> 0<14> 0<15>
// [1,1] [2,2] [3,3] [4,4] [5,5] [6,6] [7,7] [8,8]
//n<=2^k=P+P/2+P/4 ... +1
//
//suma(2^i) i=1..k
//5->8->16
//suport daca n<=2^k am nevoie de 2^(k+1)pozitii
//100000<=2^17->2^18