#include <fstream>
#include <algorithm>
#include <iostream>
using namespace std;
int numere[100010];
int arb_int[400010];
void arbore_compunere(int nod , int left, int right)
{
if (left == right)
arb_int[nod] = numere[left];
else
{//completam arborele pe partea stanga atunci cand nu sunt pe cazul de capete egale// moment in care am epuizat cazurile pe acel nod
int mij= (left + right) / 2;
arbore_compunere(nod * 2,left, mij);
arbore_compunere(nod * 2 + 1, mij + 1, right);
arb_int[nod] = max(arb_int[nod * 2], arb_int[nod * 2 + 1]);
}
}
void update(int nod, int arb_left, int arb_right, int val, int pos)
{
if (arb_left == arb_right)
{
arb_int[nod] = val;
return;
}
if ((arb_left + arb_right)/2 >= pos)
update(nod*2, arb_left, (arb_left + arb_right)/2, val, pos);
else
update(nod * 2 + 1, (arb_left + arb_right)/2 +1, arb_right, val, pos);
arb_int[nod] = max(arb_int[nod * 2], arb_int[nod * 2 + 1]);
}
int max_find(int nod, int arb_left, int arb_right, int start, int finish)
{
if(arb_left > finish || arb_right < start) return 0;
if (arb_left >= start && arb_right <= finish)
return arb_int[nod];
int mij = (arb_left + arb_right) / 2;
return max(max_find(nod * 2, arb_left, mij, start, finish), max_find(nod * 2 + 1, mij + 1, arb_right, start, finish));
}
int main() {
ifstream finput("arbint.in");
ofstream foutput("arbint.out");
int n, m;
finput >> n >> m;
for (int i = 1; i <= n; i++)
finput >> numere[i];
arbore_compunere(1, 1, n);
for (int i = 0; i < m; i++) {
int op, a, b;
finput >> op >> a >> b;
///0 a b - Sa se determine maximul din intervalul [a,b] (maximul dintre valorile Ai cu a ≤ i ≤ b).
if (op == 0)
foutput << max_find(1, 1, n, a, b) << '\n';
///1 a b - Valoarea elementului de pe pozitia a va deveni b
else if (op == 1)
update(1, 1, n, b, a);
}
return 0;
}