#include <fstream>
#include <vector>
using namespace std;
ifstream f("arbint.in");
ofstream g("arbint.out");
static constexpr int NMAX = ((int)(1e5) + 1);
static const int INF = ((int)(1e9) + 1);
class SegmentTree
{
int t[NMAX];
private:
static inline int my_max(const int &a, const int &b)
{
return ((a > b) ? a : b);
}
public:
inline void init(const int &node, const int &a, const int &b, const vector<int> &V)
{
if (a == b)
{
t[node] = V[(a - 1)];
return;
}
int mid = ((a + b) >> 1);
init((node << 1), a, mid, V);
init(((node << 1) + 1), (mid + 1), b, V);
t[node] = my_max(t[(node << 1)], t[((node << 1) + 1)]);
return;
}
inline void update(const int &node, const int &a, const int &b, const int &pos, const int &val)
{
if (a == b)
{
t[node] = val;
return;
}
int mid = ((a + b) >> 1);
if (pos <= mid)
update((node << 1), a, mid, pos, val);
else
update(((node << 1) + 1), (mid + 1), b, pos, val);
t[node] = my_max(t[(node << 1)], t[((node << 1) + 1)]);
return;
}
inline int query(const int &node, const int &a, const int &b, const int &qa, const int &qb)
{
if (qa <= a && b <= qb)
return t[node];
int mid = ((a + b) >> 1);
int p_1 = -INF, p_2 = -INF;
if (qa <= mid)
p_1 = query((node << 1), a, mid, qa, qb);
if (qb > mid)
p_2 = query(((node << 1) + 1), (mid + 1), b, qa, qb);
return my_max(p_1, p_2);
}
};
int main()
{
f.tie(nullptr);
int n = 0, m = 0;
f >> n >> m;
vector<int> v = {};
for (int i = 1; i <= n; ++i)
{
int x = 0;
f >> x;
v.push_back(x);
}
SegmentTree tree;
tree.init(1, 1, n, v);
for (int q = 1; q <= m; ++q)
{
short int type = 0;
int a = 0, b = 0;
f >> type >> a >> b;
if (type == 0)
g << tree.query(1, 1, n, a, b) << '\n';
else
tree.update(1, 1, n, a, b);
}
return 0;
}