#include <algorithm>
#include <fstream>
#include <iterator>
#include <limits>
#include <vector>
constexpr int MAX_TREE_SIZE = (1 << 18) - 1;
class Tree
{
std::vector<int> tree;
int n_elements;
public:
Tree(const std::vector<int> &v)
: tree(MAX_TREE_SIZE, 0), n_elements(v.size())
{
for (int i = 0; i < this->n_elements; ++i)
{
this->insert(v[i], i);
}
}
void insert(const int value, const int pos)
{
this->insert(value, pos, 0, 0, this->n_elements);
}
int max(const int l, const int r)
{
return this->max(l, r, 0, 0, this->n_elements);
}
private:
void insert(const int x, const int pos, const int i, const int l, const int r)
{
if (r - l == 1)
{
tree[i] = x;
return;
}
int middle = l + (r - l) / 2;
if (pos < middle)
this->insert(x, pos, 2 * i + 1, l, middle);
else
this->insert(x, pos, 2 * i + 2, middle, r);
tree[i] = std::max(tree[2 * i + 1], tree[2 * i + 2]);
}
int max(const int a, const int b, const int i, const int l, const int r)
{
if (a <= l && r <= b)
{
return tree[i];
}
int middle = l + (r - l) / 2;
int u, v;
u = v = std::numeric_limits<int>::min();
if (a < middle)
u = this->max(a, b, 2 * i + 1, l, middle);
if (middle < b)
v = this->max(a, b, 2 * i + 2, middle, r);
return std::max(u, v);
}
};
int main()
{
std::ifstream fin("arbint.in");
std::ofstream fout("arbint.out");
int n, m;
fin >> n >> m;
std::vector<int> v;
std::copy_n(std::istream_iterator<int>(fin), n, std::back_inserter(v));
Tree tree(v);
int op, a, b;
while (m--)
{
fin >> op >> a >> b;
switch (op)
{
case 0:
fout << tree.max(a - 1, b) << '\n';
break;
case 1:
tree.insert(b, a - 1);
break;
}
}
return 0;
}