#include <algorithm>
#include <cmath>
#include <fstream>
#include <iterator>
#include <limits>
#include <vector>
class IntervalTree
{
public:
IntervalTree(const std::vector<int> &v);
void Add(int pos, int value);
int Get(int a, int b) const;
private:
std::vector<int> tree;
int size;
void add(int pos, int value, int i, int l, int r);
int get(int a, int b, int i, int l, int r) const;
};
main()
{
std::ifstream fin("arbint.in");
std::ofstream fout("arbint.out");
int n, m, op, a, b;
std::vector<int> v;
fin >> n >> m;
std::copy_n(std::istream_iterator<int>(fin), n, std::back_inserter(v));
IntervalTree t(v);
while (fin >> op >> a >> b)
{
switch (op)
{
case 0:
a--, b--;
fout << t.Get(a, b) << '\n';
break;
case 1:
a--;
t.Add(a, b);
break;
}
}
return 0;
}
IntervalTree::IntervalTree(const std::vector<int> &v)
{
size = v.size();
// compute size of list which will hold the tree
int h = std::ceil(std::log2(size));
int n = std::pow(2, h + 1) - 1;
tree = std::vector<int>(n, std::numeric_limits<int>::min());
for (int i = 0; i < v.size(); i++)
{
Add(i, v[i]);
}
}
void IntervalTree::Add(int pos, int value)
{
add(pos, value, 0, 0, size - 1);
}
int IntervalTree::Get(int a, int b) const
{
return get(a, b, 0, 0, size - 1);
}
void IntervalTree::add(int pos, int value, int i, int l, int r)
{
if (l == r)
{
tree[i] = value;
return;
}
int m = l + (r - l) / 2;
if (pos <= m)
{
add(pos, value, 2 * i + 1, l, m);
}
else
{
add(pos, value, 2 * i + 2, m + 1, r);
}
tree[i] = std::max(tree[2 * i + 1], tree[2 * i + 2]);
}
int IntervalTree::get(int a, int b, int i, int l, int r) const
{
if (a <= l && r <= b)
{
return tree[i];
}
int m = l + (r - l) / 2;
int maxLeft, maxRight;
maxLeft = a <= m ? get(a, b, 2 * i + 1, l, m) : std::numeric_limits<int>::min();
maxRight = m < b ? get(a, b, 2 * i + 2, m + 1, r) : std::numeric_limits<int>::min();
return std::max(maxLeft, maxRight);
}