#include <fstream>
#include <functional>
#include <iostream>
using namespace std;
ifstream inf("arbint.in");
ofstream outf("arbint.out");
template <typename T, T neutral_val, typename BinaryOperation>
struct IntervalTree {
struct Node {
T value;
int left, right;
};
std::vector<Node> tree;
BinaryOperation op;
IntervalTree(BinaryOperation op, const std::vector<T>& data) : op(op) {
int n = data.size();
tree.resize(4 * n);
build(0, 0, n - 1, data);
}
void build(int node, int start, int end, const std::vector<T>& data) {
if (start == end) {
tree[node].value = data[start];
tree[node].left = tree[node].right = start;
} else {
int mid = (start + end) / 2;
build(2 * node + 1, start, mid, data);
build(2 * node + 2, mid + 1, end, data);
tree[node].value = op(tree[2 * node + 1].value, tree[2 * node + 2].value);
tree[node].left = start;
tree[node].right = end;
}
}
T query(int node, int start, int end) {
if (start > tree[node].right || end < tree[node].left) {
return neutral_val;
}
if (start <= tree[node].left && end >= tree[node].right) {
return tree[node].value;
}
return op(query(2 * node + 1, start, end), query(2 * node + 2, start, end));
}
T query(int start, int end) { return query(0, start, end); }
void print(int node = 0) {
cout << "Node " << node << ": [" << tree[node].left << ", " << tree[node].right << "] = " << tree[node].value
<< "\n";
if (tree[node].left != tree[node].right) {
print(2 * node + 1);
print(2 * node + 2);
}
}
void update(int node, int index, T value) {
if (tree[node].left == tree[node].right) {
tree[node].value = value;
} else {
int mid = (tree[node].left + tree[node].right) / 2;
if (index <= mid) {
update(2 * node + 1, index, value);
} else {
update(2 * node + 2, index, value);
}
tree[node].value = op(tree[2 * node + 1].value, tree[2 * node + 2].value);
}
}
void update(int index, T value) { update(0, index, value); }
void print_tree() {
for (int i = 0; i < tree.size(); ++i) {
cout << "Node " << i << ": [" << tree[i].left << ", " << tree[i].right << "] = " << tree[i].value << "\n";
}
}
};
int main() {
int n, m;
inf >> n >> m;
std::vector<int> data(n);
for (int i = 0; i < n; ++i) {
inf >> data[i];
}
auto op = [](int a, int b) { return std::max(a, b); };
IntervalTree<int, 0, decltype(op)> tree(op, data);
for (int i = 0; i < m; ++i) {
int type, x, y;
inf >> type >> x >> y;
if (type == 1) {
tree.update(x - 1, y);
} else {
outf << tree.query(x - 1, y - 1) << "\n";
}
}
return 0;
}