#include <bits/stdc++.h>
#define NMAX 100002
using namespace std;
ifstream in("arbint.in");
ofstream out("arbint.out");
int n;
int a[NMAX];
int aint[4*NMAX];
void construire(int nod, int st, int dr) ///construim arborele de intervale
{
if(st==dr)
{
aint[nod]=a[st];
return;
}
int mij=st+(dr-st)/2;
construire(nod*2, st, mij);
construire(nod*2+1, mij+1, dr);
aint[nod]=max(aint[nod*2], aint[nod*2+1]);
}
void actualizare(int poz, int val, int nod, int st, int dr)
{
if(st==dr) ///daca am ajuns la pozitia poz
{
aint[nod]=val;
return;
}
int mij=st+(dr-st)/2; ///mijlocul intervalului
if(poz<=mij) ///daca pozitia se afla in prima jumatate a intervalului
{
actualizare(poz, val, nod*2, st, mij);
}
else ///daca pozitia se afla in a doua jumatate a intervalului
{
actualizare(poz, val, nod*2+1, mij+1, dr);
}
aint[nod]=max(aint[nod*2], aint[nod*2+1]); ///combinam cele 2 intervale
}
int query(int a, int b, int nod, int st, int dr)
{
if(a>dr || b<st) ///daca intervalul este complet in afara
return 0;
if(a<=st && b>=dr) ///daca intervalul este complet inclus
return aint[nod];
int mij=st+(dr-st)/2; ///mijlocul intervalului
return max(query(a, b, nod*2, st, mij), query(a, b, nod*2+1, mij+1, dr));
}
int main()
{
int m;
in >> n >> m;
for(int i=1; i<=n; i++)
{
in >> a[i];
}
construire(1, 1, n);
while(m--)
{
int tip, a, b;
in >> tip >> a >> b;
if(tip==0)
{
out << query(a, b, 1, 1, n) << "\n";
}
else
{
actualizare(a, b, 1, 1, n);
}
}
return 0;
}