#include <bits/stdc++.h>
using namespace std;
string np = "arbint";
ifstream f(np + ".in");
ofstream g(np + ".out");
// #define f cin
// #define g cout
struct segtree
{
int size = 1;
vector<int> val;
void init(int n)
{
while (size < n)
size *= 2;
val.resize(size * 2);
}
void build(vector<int> &aux, int nod, int stnod, int drnod)
{
if (drnod - stnod == 1)
{
if (stnod < (int)aux.size())
val[nod] = aux[stnod];
return;
}
int mid = (stnod + drnod) / 2;
build(aux, nod * 2 + 1, stnod, mid);
build(aux, nod * 2 + 2, mid, drnod);
val[nod] = max(val[nod * 2 + 1], val[nod * 2 + 2]);
}
void build(vector<int> &aux)
{
build(aux, 0, 0, size);
}
void set(int poz, int valoare, int nod, int stnod, int drnod)
{
if (drnod - stnod == 1)
{
val[nod] = valoare;
return;
}
int mid = (stnod + drnod) / 2;
if (poz < mid)
set(poz, valoare, nod * 2 + 1, stnod, mid);
else
set(poz, valoare, nod * 2 + 2, mid, drnod);
val[nod] = max(val[nod * 2 + 1], val[nod * 2 + 2]);
}
void set(int poz, int valoare)
{
set(poz, valoare, 0, 0, size);
}
int maxim(int st, int dr, int nod, int stnod, int drnod)
{
if (stnod >= dr or drnod <= st)
return 0;
if (stnod >= st and drnod <= dr)
return val[nod];
int mid = (stnod + drnod) / 2;
int maxim1 = maxim(st, dr, nod * 2 + 1, stnod, mid);
int maxim2 = maxim(st, dr, nod * 2 + 2, mid, drnod);
return max(maxim1, maxim2);
}
int maxim(int st, int dr)
{
return maxim(st, dr, 0, 0, size);
}
} mst;
int main()
{
ios_base::sync_with_stdio(false);
f.tie(nullptr);
int n, m;
f >> n >> m;
mst.init(n);
vector<int> aux(n);
for (int i = 0; i < n; i++)
f >> aux[i];
mst.build(aux);
for (int cer; f >> cer;)
if (cer == 0)
{
int st, dr;
f >> st >> dr;
g << mst.maxim(st - 1, dr) << '\n';
}
else
{
int poz, val;
f >> poz >> val;
mst.set(poz - 1, val);
}
return 0;
}