//#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
ifstream cin("arbint.in");
ofstream cout("arbint.out");
const int NMAX = 100005;
int tree[4 * NMAX], A[NMAX];
int n;
void build(int arr[], int v, int tl, int tr) {
if (tl == tr) {
tree[v] = arr[tl];
}
else {
int tm = (tl + tr) / 2;
build(arr, 2 * v, tl, tm);
build(arr, 2 * v + 1, tm + 1, tr);
tree[v] = max(tree[2 * v], tree[2 * v + 1]);
}
}
int query(int v, int tl, int tr, int l, int r) {
if (l == tl && r == tr) {
return tree[v];
}
int tm = (tl + tr) / 2;
return max(query(2 * v, tl, tm, l, min(r, tm)), query(2 * v + 1, tm + 1, tr, max(l, tm + 1), r));
}
void update(int v, int tl, int tr, int pos, int new_val) {
if (tl == tr) {
tree[v] = new_val;
}
else {
int tm = (tl + tr) / 2;
if (pos <= tm) {
update(2 * v, tl, tm, pos, new_val);
}
else {
update(2 * v + 1, tm + 1, tr, pos, new_val);
}
tree[v] = max(tree[2 * v], tree[2 * v + 1]);
}
}
int main() {
int N, M;
cin >> N >> M;
for (int i = 0; i < N; ++i) {
cin >> A[i];
}
n = N;
build(A, 1, 0, n - 1);
for (int i = 0; i < M; ++i) {
int type, a, b;
cin >> type >> a >> b;
if (type == 0) {
cout << query(1, 0, n - 1, a - 1, b - 1) << endl;
}
else if (type == 1) {
update(1, 0, n - 1, a - 1, b);
}
}
return 0;
}