#include <iostream>
#include <cstdio>
using namespace std;
typedef struct
{
long a;
long b;
long v;
}
ArbInt;
ArbInt AI[500005];
long N, V[100005];
long Max (long a, long b)
{
if (a>b)
{
return a;
}
return b;
}
void BuildTree (long Left, long Right, long K)
{
long Middle;
AI[K].a=Left;
AI[K].b=Right;
Middle=(Left+Right)/2;
if (Left==Right)
{
AI[K].v=V[Middle];
}
else
{
BuildTree (Left, Middle, 2*K);
BuildTree (Middle+1, Right, 2*K+1);
AI[K].v=Max (AI[2*K].v, AI[2*K+1].v);
}
}
void Update (long x, long y, long K)
{
long Middle;
Middle=(AI[K].a+AI[K].b)/2;
if (AI[K].a==AI[K].b)
{
AI[K].v=y;
}
else
{
if (x<=Middle)
{
Update (x, y, 2*K);
}
else
{
Update (x, y, 2*K+1);
}
AI[K].v=Max (AI[2*K].v, AI[2*K+1].v);
}
}
long long Query (long Left, long Right, long K)
{
long long S=0;
long Middle;
if ((Left==AI[K].a)&&(Right==AI[K].b))
{
return AI[K].v;
}
Middle=(AI[K].a+AI[K].b)/2;
if (Left>Middle)
{
S=Query (Left, Right, 2*K+1);
}
if (Right<=Middle)
{
S=Query (Left, Right, 2*K);
}
if ((Left<=Middle)&&(Right>Middle))
{
S=Max (Query (Left, Middle, 2*K), Query (Middle+1, Right, 2*K+1));
}
return S;
}
int main()
{
FILE *fin = fopen ("arbint.in", "r");
FILE *fout = fopen ("arbint.out", "w");
long M, i, Tip, a, b;
fscanf (fin, "%ld%ld", &N, &M);
for (i=0; i<N; i++)
{
fscanf (fin, "%ld", &V[i]);
}
BuildTree (0, N-1, 1);
for (i=0; i<M; i++)
{
fscanf (fin, "%ld%ld%ld", &Tip, &a, &b);
if (Tip==0)
{
a--;
b--;
fprintf (fout, "%lld\n", Query (a, b, 1));
}
if (Tip==1)
{
a--;
Update (a, b, 1);
}
}
fclose (fin);
fclose (fout);
return 0;
}