#include <iostream>
#include <fstream>
using namespace std;
unsigned int *tree;
int max(int a, int b)
{
if (a > b) {
return a;
}
return b;
}
unsigned int buildTree(unsigned int *v, unsigned int node, int left, int right)
{
if (left == right)
{
tree[node] = v[left];
return v[left];
}
int mid = (left + right) / 2;
int maxLeft = buildTree(v, node * 2, left, mid);
int maxRight = buildTree(v, node * 2 + 1, mid + 1, right);
tree[node] = max(maxLeft, maxRight);
return tree[node];
}
void update_pos(unsigned int *v, unsigned int node, int left, int right, unsigned int pos, unsigned int value)
{
if (left == right)
{
tree[node] = value;
return;
}
int mid = (left + right) / 2;
if (pos <= mid) {
update_pos(v, node * 2, left, mid, pos, value);
}
else {
update_pos(v, node * 2 + 1, mid + 1, right, pos, value);
}
tree[node] = max(tree[node * 2], tree[node * 2 + 1]);
}
int query(unsigned int *v, unsigned int node, int left, int right, unsigned int a, unsigned int b)
{
if (a <= left && right <= b) {
return tree[node];
}
int mid = (left + right) / 2;
int maxLeft = -1, maxRight = -1;
if (a <= mid) {
maxLeft = query(v, node * 2, left, mid, a, b);
}
if (mid < b) {
maxRight = query(v, node * 2 + 1, mid + 1, right, a, b);
}
return max(maxLeft, maxRight);
}
int main()
{
ifstream fin("arbint.in");
ofstream fout("arbint.out");
unsigned int n, m, i;
fin >> n >> m;
unsigned int *v = new unsigned int[n + 1];
for (i = 1; i <= n; ++i) {
fin >> v[i];
}
tree = new unsigned int[4 * n + 1];
buildTree(v, 1, 1, n);
unsigned int a, b;
bool op;
while (m)
{
fin >> op >> a >> b;
if (op == false) {
fout << query(v, 1, 1, n, a, b) << '\n';
}
else {
update_pos(v, 1, 1, n, a, b);
}
--m;
}
fin.close();
fout.close();
return 0;
}