#include <iostream>
#include <fstream>
#include <vector>
struct SegmentTree {
private:
std::vector<int> tree;
std::vector<int> *ptr;
int size;
void build(int node, int left, int right) {
if (left == right)tree[node] = (*ptr)[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) {
if (left == right)tree[node] = (*ptr)[left];
else {
int mid = (left + right) / 2;
if (pos <= mid) update(2 * node, left, mid, pos);
else update(2 * node + 1, mid + 1, right, pos);
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 INT32_MIN;
int mid = (left + right) / 2;
return std::max(query(2 * node, left, mid, start, end), query(2 * node + 1, mid + 1, right, start, end));
}
public:
SegmentTree(int size, std::vector<int> &ref) : size(size), ptr(&ref) {
tree.resize(size * 4 + 1, 0);
build(1, 1, size);
}
void update(int pos, int value) {
(*ptr)[pos] = value;
update(1, 1, size, pos);
}
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, 0);
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;
}