#include <fstream>
#include <vector>
using namespace std;
vector<int> segment_tree, v;
void build(int node, int left, int right) {
if (left == right)
segment_tree[node] = v[left];
else {
int middle = (left + right) / 2;
build(2 * node, left, middle);
build(2 * node + 1, middle + 1, right);
segment_tree[node] = max(segment_tree[2 * node], segment_tree[2 * node + 1]);
}
}
void update(int node, int left, int right, int position, int new_value) {
if (left == right)
segment_tree[node] = new_value;
else {
int middle = (left + right) / 2;
if (position <= middle)
update(2 * node, left, middle, position, new_value);
else
update(2 * node + 1, middle + 1, right, position, new_value);
segment_tree[node] = max(segment_tree[2 * node], segment_tree[2 * node + 1]);
}
}
int query(int node, int left, int right, int query_left, int query_right) {
if (query_left <= left && right <= query_right)
return segment_tree[node];
else {
int middle = (left + right) / 2;
if (query_right <= middle)
return query(2 * node, left, middle, query_left, query_right);
if (middle + 1 <= query_left)
return query(2 * node + 1, middle + 1, right, query_left, query_right);
return max(query(2 * node, left, middle, query_left, query_right), query(2 * node + 1, middle + 1, right, query_left, query_right));
}
}
int main() {
ifstream fin("arbint.in");
ofstream fout("arbint.out");
int n, m;
fin >> n >> m;
v.resize(n + 1);
segment_tree.resize(4 * n);
for (int i = 1; i <= n; ++i)
fin >> v[i];
build(1, 1, n);
for (int i = 1; i <= m; ++i) {
int op, a, b;
fin >> op >> a >> b;
if (op == 0)
fout << query(1, 1, n, a, b) << '\n';
else
update(1, 1, n, a, b);
}
return 0;
}