#include <fstream>
#include <iostream>
#define NMAX 100000
#define IN(a, b, c) ((b) <= (a) && (a) <= (c))
#define IN(a, b, c, d) ((c) <= (a) && (b) <= (d))
using namespace std;
int tree[2 * NMAX + 10];
int query(int a, int b, int poz, int l1, int l2) {
if (IN(l1, l2, a, b)) return tree[poz];
int rez = 0;
int mid = (l1 + l2) / 2;
if (a <= mid) rez = max(rez, query(a, b, poz * 2, l1, mid));
if (b > mid) rez = max(rez, query(a, b, poz * 2 + 1, mid + 1, l2));
return rez;
}
void update(int i, int val, int poz, int l1, int l2) {
//cout<<"update: "<<i<<' '<<val<<' '<<poz<<' '<<l1<<' '<<l2<<'\n';
if (l1 == l2 && l2 == i) {
//cout<<"leaving..\n";
tree[poz] = val;
poz /= 2;
while (poz) {
tree[poz] = max(tree[poz * 2], tree[poz * 2 + 1]);
poz /= 2;
}
return;
}
int mid = (l1 + l2) / 2;
if (i <= mid) {
update(i, val, poz * 2, l1, mid);
return;
}
update(i, val, poz * 2 + 1, mid + 1, l2);
return;
}
int main() {
ifstream fin("arbint.in");
ofstream fout("arbint.out");
int n, m;
fin>>n>>m;
int size = 1;
{
int low = 1;
while (low != n) {
low = (n + low) / 2 + 1;
size = size * 2 + 1;
}
}
for (int i = 1; i <= n; i++) {
int val;
fin>>val;
update(i, val, 1, 1, n);
//for (int j = 1; j <= size; j++) cout<<tree[j]<<' ';
//cout<<'\n';
}
for (int i = 0; i < m; i++) {
int q, a, b;
fin>>q>>a>>b;
if (!q) fout<<query(a, b, 1, 1, n)<<'\n';
else update(a, b, 1, 1, n);
//for (int j = 1; j <= size; j++) cout<<tree[j]<<' ';
//cout<<'\n';
}
}