#include <cstdio>
#include <cmath>
#include <climits>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <bitset>
#include <map>
#include <cstring>
#include <algorithm>
#define NMAX 100003
using namespace std;
FILE* fin, * fout;
int n, m;
int v[NMAX],maxim;
int arb[4 * NMAX];
void build(int nod, int st, int dr)
{
if (st == dr)
{
arb[nod] = v[st];
}
else {
int mij = (st + dr) / 2;
build(2 * nod, st, mij);
build(2 * nod + 1, mij + 1, dr);
arb[nod] = max(arb[2 * nod], arb[2 * nod + 1]);
}
}
void update(int nod, int st, int dr,int poz)
{
if (st == dr)
{
//suntem in poz
arb[nod] = v[st];
}
else {
int mij = (st + dr) / 2;
if (poz <= mij)
{
update(2 * nod, st, mij,poz);
}
else {
update(2 * nod + 1, mij + 1, dr,poz);
}
arb[nod] = max(arb[2 * nod], arb[2 * nod + 1]);
}
}
void query(int nod, int st, int dr, int qSt, int qDr)
{
if (qSt <= st && dr<=qDr)
{
maxim = max(arb[nod], maxim);
}
else {
int mij = (st + dr) / 2;
if (qSt <= mij)
{
query(2 * nod, st, mij,qSt,qDr);
}
if(mij+1<=qDr) {
query(2 * nod + 1, mij + 1, dr, qSt, qDr);
}
}
}
int main()
{
fin = fopen("arbint.in", "r");
fout = fopen("arbint.out", "w");
fscanf(fin, "%d %d\n", &n, &m);
for (int i = 1; i <= n; i++)
{
fscanf(fin, "%d", &v[i]);
}
build(1, 1, n);
for (int i = 1; i <= m; i++)
{
int cer;
fscanf(fin, "%d\n", &cer);
if (cer == 0)
{
int st, dr;
fscanf(fin, "%d %d\n", &st, &dr);
maxim = INT_MIN;
query(1, 1, n, st, dr);
fprintf(fout, "%d\n", maxim);
}
else if (cer == 1)
{
int a, b;
fscanf(fin, "%d %d\n", &a, &b);
v[a] = b;
update(1, 1, n, a);
}
}
return 0;
}