#include <bits/stdc++.h>
using namespace std;
ifstream fin("arbint.in");
ofstream fout("arbint.out");
bool ininterv(int x, int st, int sf) {
return st <= x && x <= sf;
}
struct Arbore {
vector<int> arb;
Arbore(int n) : arb(5 * n, 0) {
}
void set(int poz, int val, int st, int sf, int idx = 1) {
if (st == sf) {
arb[idx] = val;
return;
}
int mij = (st + sf) / 2;
if (poz <= mij) {
set(poz, val, st, mij, 2 * idx);
} else {
set(poz, val, mij + 1, sf, 2 * idx + 1);
}
arb[idx] = max(arb[idx * 2], arb[idx * 2 + 1]);
}
int get(int l, int r, int st, int sf, int idx = 1) {
// 8 9 9 10
if (!ininterv(l, st, sf) && !ininterv(st, l, r)) {
// fout << ininterv(l, st, sf) << " " << ininterv(sf, l, r) << " " << st << " " << sf
// << " " << 0 << "\n";
return 0;
}
if (st == sf) {
// fout << st << " " << sf << " " << arb[idx] << "\n";
return arb[idx];
}
int mij = (st + sf) / 2;
int m1 = get(l, r, st, mij, idx * 2);
int m2 = get(l, r, mij + 1, sf, idx * 2 + 1);
// fout << st << " " << sf << " " << max(m1, m2) << "\n";
return max(m1, m2);
}
};
int main() {
int n, m, c, x, y;
fin >> n >> m;
Arbore a(n);
for (int i = 1; i <= n; i++) {
fin >> x;
a.set(i, x, 1, n);
}
// for (int i = 1; i <= n; i++) {
// fout << a.get(i, i, 1, n) << "\n";
// }
for (int i = 0; i < m; i++) {
fin >> c >> x >> y;
if (c) {
a.set(x, y, 1, n);
} else {
fout << a.get(x, y, 1, n) << "\n";
}
}
}