#include <fstream>
#include <iostream>
#include <vector>
using namespace std;
struct SegmentTree {
struct Node {
int interval_max;
Node(int interval_max = 0) : interval_max(interval_max) {
}
void RebuildSelf(const Node& left, const Node& right) {
interval_max = max(left.interval_max, right.interval_max);
}
};
static const Node undefined_node;
int n;
vector<Node> els;
void Init(vector<Node> initial_nodes) {
n = initial_nodes.size();
els = vector<Node>(4 * n, undefined_node);
Init(1, 0, n - 1, initial_nodes);
}
void Init(int node, int left, int right, vector<Node> initial_nodes) {
if (left == right) {
els[node] = initial_nodes[left];
} else {
int mid = (left + right) / 2;
Init(2 * node, left, mid, initial_nodes);
Init(2 * node + 1, mid + 1, right, initial_nodes);
els[node].RebuildSelf(
els[2 * node],
els[2 * node + 1]
);
}
}
void Update(int pos, const Node& new_node) {
Update(1, 0, n - 1, pos, new_node);
}
void Update(int node, int left, int right, int pos, const Node& new_node) {
if (left == right) {
els[node] = new_node;
} else {
int mid = (left + right) / 2;
if (pos <= mid) {
Update(2 * node, left, mid, pos, new_node);
} else {
Update(2 * node + 1, mid + 1, right, pos, new_node);
}
els[node].RebuildSelf(
els[2 * node],
els[2 * node + 1]
);
}
}
Node Query(int c1, int c2) {
return Query(1, 0, n - 1, c1, c2);
}
Node Query(int node, int left, int right, int c1, int c2) {
if (right < c1 or c2 < left) {
return undefined_node;
}
if (c1 <= left and right <= c2) {
return els[node];
}
int mid = (left + right) / 2;
auto l = Query(2 * node, left, mid, c1, c2);
auto r = Query(2 * node + 1, mid + 1, right, c1, c2);
Node ans;
ans.RebuildSelf(l, r);
return ans;
}
};
const SegmentTree::Node SegmentTree::undefined_node(0);
int main() {
ifstream cin("arbint.in");
ofstream cout("arbint.out");
int n, q; cin >> n >> q;
vector<SegmentTree::Node> initial_els(n);
for (auto& itr : initial_els) {
int x; cin >> x;
itr.interval_max = x;
}
SegmentTree st;
st.Init(initial_els);
while (q--) {
int type; cin >> type;
if (type == 0) {
int c1, c2; cin >> c1 >> c2;
c1 -= 1;
c2 -= 1;
cout << st.Query(c1, c2).interval_max << '\n';
} else {
int pos, val; cin >> pos >> val;
pos -= 1;
st.Update(pos, SegmentTree::Node(val));
}
}
}