#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
ifstream fin("arbint.in");
ofstream fout("arbint.out");
class SegmentTree {
private:
vector<int> tree;
int n;
void build(const vector<int>& arr, int node, int left, int right) {
if (left == right) {
tree[node] = arr[left];
return;
}
int mid = (left + right) / 2;
build(arr, node * 2, left, mid);
build(arr, node * 2 + 1, mid + 1, right);
tree[node] = max(tree[node * 2], tree[node * 2 + 1]);
}
void update(int node, int left, int right, int pos, int val) {
if (left == right) {
tree[node] = val;
return;
}
int mid = (left + right) / 2;
if (pos <= mid)
update(node * 2, left, mid, pos, val);
else
update(node * 2 + 1, mid + 1, right, pos, val);
tree[node] = max(tree[node * 2], tree[node * 2 + 1]);
}
int query(int node, int left, int right, int qLeft, int qRight) {
if (qLeft <= left && right <= qRight)
return tree[node];
int mid = (left + right) / 2;
int res = -1;
if (qLeft <= mid)
res = max(res, query(node * 2, left, mid, qLeft, qRight));
if (qRight > mid)
res = max(res, query(node * 2 + 1, mid + 1, right, qLeft, qRight));
return res;
}
public:
SegmentTree(const vector<int>& arr) {
n = arr.size();
tree.resize(4 * n);
build(arr, 1, 0, n - 1);
}
void update(int pos, int val) {
update(1, 0, n - 1, pos, val);
}
int query(int left, int right) {
return query(1, 0, n - 1, left, right);
}
};
int main() {
int N, M;
fin >> N >> M;
vector<int> arr(N);
for (int i = 0; i < N; ++i)
fin >> arr[i];
SegmentTree st(arr);
for (int i = 0; i < M; ++i) {
int op, a, b;
fin >> op >> a >> b;
if (op == 0) {
fout << st.query(a - 1, b - 1) << '\n';
} else {
st.update(a - 1, b);
}
}
return 0;
}