#include <iostream>
#include <fstream>
#include <vector>
#include <climits>
struct SegmentTree {
private:
std::vector<int> tree;
std::vector<int> arr;
int size;
void build(int node, int left, int right) {
if (left == right) {
tree[node] = arr[left];
} else {
int mid = (left + right) / 2;
build(2 * node, left, mid);
build(2 * node + 1, mid + 1, right);
tree[node] = std::max(tree[2 * node], tree[2 * node + 1]);
}
}
void update(int node, int left, int right, int pos, int value) {
if (left == right) {
arr[left] = value;
tree[node] = value;
} else {
int mid = (left + right) / 2;
if (pos <= mid) {
update(2 * node, left, mid, pos, value);
} else {
update(2 * node + 1, mid + 1, right, pos, value);
}
tree[node] = std::max(tree[2 * node], tree[2 * node + 1]);
}
}
int query(int node, int left, int right, int start, int end) {
if (start <= left && right <= end) {
return tree[node];
}
if (end < left || right < start) {
return INT_MIN;
}
int mid = (left + right) / 2;
int left_query = query(2 * node, left, mid, start, end);
int right_query = query(2 * node + 1, mid + 1, right, start, end);
return std::max(left_query, right_query);
}
public:
SegmentTree(int n, std::vector<int> &v) : size(n), arr(v) {
tree.resize(4 * n + 1, 0);
build(1, 1, n);
}
void update(int pos, int value) {
update(1, 1, size, pos, value);
}
int query(int start, int end) {
return query(1, 1, size, start, end);
}
};
int main() {
std::ifstream input("arbint.in");
std::ofstream output("arbint.out");
int n, m;
input >> n >> m;
std::vector<int> v(n + 1);
for (int i = 1; i <= n; ++i) {
input >> v[i];
}
SegmentTree tree(n, v);
while (m--) {
int op, a, b;
input >> op >> a >> b;
if (op == 0) {
output << tree.query(a, b) << '\n';
} else {
tree.update(a, b);
}
}
return 0;
}