#include <fstream>
#include <vector>
class SegmentTree {
protected:
std::vector<int> tree;
int length;
void build(const std::vector<int> &nums, int node, int l, int r) {
if (l == r) {
tree[node] = nums[l];
return;
}
int mid = l + (r - l) / 2;
build(nums, node * 2 + 1, l, mid);
build(nums, node * 2 + 2, mid + 1, r);
tree[node] = std::max(tree[node * 2 + 1], tree[node * 2 + 2]);
}
long long max_in_range(int node, int l, int r, int ql, int qr) {
if (ql > qr) {
return 0;
}
if (l == ql && r == qr) {
return tree[node];
}
int mid = l + (r - l) / 2;
long long result = 0;
auto new_qr = std::min(qr, mid);
if (ql <= new_qr) {
result = std::max(result,
max_in_range(2 * node + 1, l, mid, ql, new_qr));
}
auto new_ql = std::max(ql, mid + 1);
if (new_ql <= qr) {
result = std::max(
result, max_in_range(2 * node + 2, mid + 1, r, new_ql, qr));
}
return result;
}
void update(int index, int val, int node, int l, int r) {
if (l == r) {
tree[node] = val;
return;
}
int mid = l + (r - l) / 2;
if (index <= mid) {
update(index, val, 2 * node + 1, l, mid);
} else {
update(index, val, 2 * node + 2, mid + 1, r);
}
tree[node] = std::max(tree[node * 2 + 1], tree[node * 2 + 2]);
}
public:
SegmentTree(const std::vector<int> &nums) : length(nums.size()) {
tree.resize(4 * nums.size());
build(nums, 0, 0, length - 1);
}
long long max_in_range(int ql, int qr) {
return max_in_range(0, 0, length - 1, ql, qr);
}
void update(int index, int val) { update(index, val, 0, 0, length - 1); }
};
int main() {
std::ifstream ifs("arbint.in");
int n, m;
ifs >> n >> m;
std::vector<int> nums(n);
for (int i = 0; i < n; ++i) {
ifs >> nums[i];
}
SegmentTree segment_tree(nums);
std::ofstream ofs("arbint.out");
for (int q = 0; q < m; ++q) {
int op, a, b;
ifs >> op >> a >> b;
if (op == 0) {
ofs << segment_tree.max_in_range(a - 1, b - 1) << '\n';
} else {
segment_tree.update(a - 1, b);
}
}
ifs.close();
ofs.close();
return 0;
}