#include <cstdio>
#include <vector>
#include <climits>
#include <iostream>
struct Max
{
constexpr int operator()(const int a, const int b) const
{
return std::max(a, b);
}
};
template<typename Cond>
class IntTree
{
public:
IntTree(std::vector<int>& vec)
: n(vec.size())
{
data.resize(3 * n, 0);
for(unsigned i = 0; i < n; ++i)
{
insert(i + 1, i + 1, vec[i]);
}
}
void insert(const unsigned l, const unsigned r, const int value)
{
insert(1, 1, n, l, r, value);
}
int get_max(const unsigned l, const unsigned r)
{
return get_max(1, 1, n, l, r);
}
static unsigned lchild(const unsigned index)
{
return index * 2;
}
static unsigned rchild(const unsigned index)
{
return index * 2 + 1;
}
static constexpr Cond cond = Cond{};
private:
void insert(const unsigned index, const unsigned left, const unsigned right,
const unsigned l, const unsigned r, const int value)
{
if(l > right || r < left)
{
return;
}
if(left == right)
{
data[index] = value;
return;
}
const unsigned mij = left + (right - left) / 2;
const unsigned lc_idx = lchild(index);
const unsigned rc_idx = rchild(index);
if(l <= mij)
{
insert(lc_idx, left, mij, l, std::min(mij, r), value);
}
if(r > mij)
{
insert(rc_idx, mij + 1, right, std::max(mij + 1, l), r, value);
}
data[index] = Cond{}(data[lc_idx], data[rc_idx]);
}
int get_max(const unsigned index, const unsigned left, const unsigned right,
const unsigned l, const unsigned r)
{
if(l > right || r < left)
{
return INT_MIN;
}
if(l == left && r == right)
{
return data[index];
}
const unsigned mij = left + (right - left) / 2;
const unsigned lc_idx = lchild(index);
const unsigned rc_idx = rchild(index);
int a = INT_MIN;
int b = INT_MIN;
if(l <= mij)
{
a = get_max(lc_idx, left, mij, l, std::min(mij, r));
}
if(r > mij)
{
b = get_max(rc_idx, mij + 1, right, std::max(mij + 1, l), r);
}
return std::max(a, b);
}
private:
std::vector<int> data;
unsigned n;
};
int main()
{
std::freopen("arbint.in", "r", stdin);
std::freopen("arbint.out", "w", stdout);
unsigned N, M;
std::scanf("%u%u", &N, &M);
std::vector<int> vec;
vec.reserve(N);
for(unsigned i = 0; i < N; ++i)
{
int value;
std::scanf("%d", &value);
vec.push_back(value);
}
IntTree<Max> itree(vec);
for(unsigned i = 0; i < M; ++i)
{
int op, a, b;
std::scanf("%d%d%d", &op, &a, &b);
if(op == 0)
{
std::printf("%d\n", itree.get_max(a, b));
}
else
{
itree.insert(a, a, b);
}
}
}