#include <bits/stdc++.h>
using namespace std;
ifstream fin("arbint.in");
ofstream fout("arbint.out");
const int nr = 100005;
int numere[nr];
int tree[4 * nr];
int n,m;
void citire()
{
fin>>n>>m;
for(int i=1;i<=n;i++)
fin>>numere[i];
}
// construim arborele
void build_tree(int nod, int st, int dr) {
if(st == dr) {
tree[nod] = numere[st];
return;
}
int mij = (st + dr) / 2;
build_tree(2 * nod, st, mij);
build_tree(2 * nod + 1, mij + 1, dr);
tree[nod] =max( tree[2 * nod] , tree[2 * nod + 1]);
}
// modifica nr. de pe pozitia pos in val
void update(int pos, int val, int nod, int st, int dr) {
// verificam daca intervalul curent e afectat de pos
if(pos < st || pos > dr) {
return;
}
// daca ne aflam in pos, modificam valuarea
if(st == dr) {
tree[nod] = val;
return;
}
// modificam recursiv fiecare jumatate
int mij = (st + dr) / 2;
update(pos, val, 2 * nod, st, mij);
update(pos, val, 2 * nod + 1, mij + 1, dr);
tree[nod] = max(tree[2 * nod] , tree[2 * nod + 1]);
}
// suma din intervalul [a, b]
int query(int a, int b, int nod, int st, int dr) {
// [st, dr] nu e inclus in [a, b]
if(st > b || dr < a) return 0;
// [st, dr] inclus in [a, b]
if(a <= st && b >= dr) return tree[nod];
int mij = (st + dr) / 2;
int s_st = query(a, b, 2 * nod, st, mij);
int s_dr = query(a, b, 2 * nod + 1, mij + 1, dr);
return max(s_st , s_dr);
}
void solution()
{
int x,y,p;
for(int i=1;i<=m;i++)
{
fin>>p>>x>>y;
if(p==0)
fout<<query(x,y,1,1,n)<<"\n";
else
update(x,y,1,1,n);
}
}
int main() {
citire();
build_tree(1,1,n);
solution();
return 0;
}