#include <vector>
#include <fstream>
std::ifstream fin("arbint.in");
std::ofstream fout("arbint.out");
template<class T>
class SegmTree {
private:
int n;
std::vector<T> tree;
inline T max(T x, T y) {
return x > y ? x : y;
}
void build(int node, int left, int right, std::vector<T> v) {
if (left == right) {
tree[node] = v[left];
return;
}
int mid = (left + right) / 2;
build(2 * node, left, mid, v);
build(2 * node + 1, mid + 1, right, v);
tree[node] = max(tree[2 * node], tree[2 * node + 1]);
}
void update(int node, int left, int right, int pos, T val) {
if (left == pos && right == pos) {
tree[node] = val;
return;
}
int mid = (left + right) / 2;
if (pos <= mid)
update(2 * node, left, mid, pos, val);
else
update(2 * node + 1, mid + 1, right, pos, val);
tree[node] = max(tree[2 * node], tree[2 * node + 1]);
}
int query(int node, int left, int right, int qLeft, int qRight) {
if (left == right)
return tree[node];
int mid = (left + right) / 2;
if (qRight <= mid)
return query(2 * node, left, mid, qLeft, qRight);
if (qLeft > mid)
return query(2 * node + 1, mid + 1, right, qLeft, qRight);
return max(
query(2 * node, left, mid, qLeft, mid),
query(2 * node + 1, mid + 1, right, mid + 1, qRight)
);
}
public:
SegmTree(std::vector<T> v) {
n = v.size() - 1;
tree.resize(4 * n);
build(1, 1, n, v);
}
void update(int pos, T val) {
update(1, 1, n, pos, val);
}
int query(int left, int right) {
return query(1, 1, n, left, right);
}
};
int main() {
int n, q;
fin >> n >> q;
std::vector<int> v(n + 1);
for (int i = 1; i <= n; i++)
fin >> v[i];
SegmTree<int> tree(v);
for (int i = 0; i < q; i++) {
int x, y, z;
fin >> x >> y >> z;
if (!x)
fout << tree.query(y, z) << '\n';
else
tree.update(y, z);
}
fout.close();
return 0;
}