#include <fstream>
std::ifstream fin("arbint.in");
std::ofstream fout("arbint.out");
#include <array>
#include <climits>
constexpr unsigned NMAX = 100000;
constexpr unsigned DIM = 6 * NMAX;
std::array<int, DIM> data = {};
void update_leaf(const unsigned index, const unsigned begin, const unsigned end,
const unsigned pos, const int value)
{
if(begin == end)
{
data[index] = value;
return;
}
const unsigned mid = begin + (end - begin) / 2;
if(pos <= mid)
{
update_leaf(2 * index, begin, mid, pos, value);
}
else
{
update_leaf(2 * index + 1, mid + 1, end, pos, value);
}
data[index] = std::max(data[2 * index], data[2 * index + 1]);
}
void query(const unsigned index, const unsigned begin, const unsigned end,
const unsigned qleft, const unsigned qright, int& result)
{
if(qleft <= begin && end <= qright)
{
result = std::max(result, data[index]);
return;
}
const unsigned mid = begin + (end - begin) / 2;
if(qleft <= mid)
{
query(2 * index, begin, mid, qleft, qright, result);
}
if(mid < qright)
{
query(2 * index + 1, mid + 1, end, qleft, qright, result);
}
}
template<typename T>
T mread()
{
T temp;
fin >> temp;
return temp;
}
int main()
{
const auto N = mread<unsigned>();
const auto M = mread<unsigned>();
for(unsigned i = 0; i < N; ++i)
{
update_leaf(1, 1, N, i + 1, mread<int>());
}
for(unsigned i = 0; i < M; ++i)
{
const int op = mread<int>();
const int a = mread<int>();
const int b = mread<int>();
if(op == 0)
{
int result = INT_MIN;
query(1, 1, N, a, b, result);
fout << result << '\n';
}
else
{
update_leaf(1, 1, N, a, b);
}
}
}