#include <iostream>
#include <fstream>
#include <vector>
#include <cassert>
using namespace std;
#define dim 100001
struct SegmentTree {
int size;
vector<int> tree;
SegmentTree(int n) {
size = n;
tree.resize(4 * size + 66);
}
void Update(int nod, int left, int right, int pos, int val) {
if (left == right) {
tree[nod] = val;
return;
}
int mid = (left + right) / 2;
if (pos <= mid) {
Update(2 * nod, left, mid, pos, val);
} else {
Update(2 * nod + 1, mid + 1, right, pos, val);
}
tree[nod] = Maxim(tree[2 * nod], tree[2 * nod + 1]);
}
int Query(int nod, int left, int right, int start, int finish) {
if (start <= left && right <= finish) {
return tree[nod];
}
int mid = (left + right) / 2;
int maxVal = -1;
if (start <= mid) {
maxVal = Maxim(maxVal, Query(2 * nod, left, mid, start, finish));
}
if (mid < finish) {
maxVal = Maxim(maxVal, Query(2 * nod + 1, mid + 1, right, start, finish));
}
return maxVal;
}
static int Maxim(int a, int b) {
return (a > b) ? a : b;
}
};
int main() {
int N, M, X, A, B;
ifstream in ("arbint.in");
ofstream out ("arbint.out");
in >> N >> M;
SegmentTree segmentTree(N);
for (int i = 1; i <= N; i++) {
in >> X;
segmentTree.Update(1, 1, N, i, X);
}
for (int i = 1; i <= M; i++) {
cin >> X >> A >> B;
if (X == 0) {
int maxVal = segmentTree.Query(1, 1, N, A, B);
out << maxVal << endl;
} else {
segmentTree.Update(1, 1, N, A, B);
}
}
return 0;
}