#include <fstream>
#include <vector>
using namespace std;
ifstream f("arbint.in");
ofstream g("arbint.out");
class SegTree
{
int n, *t;
inline int my_max(const int a, const int b)
{
return ((a > b) ? a : b);
}
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;
}
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;
}
int query(const int node, const int a, const int b, const int qa, const int qb)
{
if (qa > qb)
return 0;
if (a > b)
return 0;
if ((qa <= a) && (b <= qb)) // stop condition
return t[node];
int mid = ((a + b) >> 1);
int p_left = (-1), p_right = (-1);
if (qa <= mid)
p_left = query((node << 1), a, mid, qa, qb);
if (qb > mid)
p_right = query(((node << 1) + 1), (mid + 1), b, qa, qb);
return my_max(p_left, p_right);
}
public:
SegTree(const int size, const vector<int> &a)
{
n = size,
t = new int[((n << 2) + 4)];
init(1, 1, n, a);
}
~SegTree()
{
delete t;
}
void update(const int pos, const int val)
{
update(1, 1, n, pos, val);
return;
}
int query(const int left, const int right)
{
return query(1, 1, n, left, right);
}
};
int main()
{
int n = 0, m = 0;
f >> n >> m;
vector<int> a(n);
for (int i = 0; i < n; ++i)
f >> a[i];
SegTree tree(n, a);
for (int q = 1; q <= m; ++q)
{
short int type = 0;
f >> type;
int a = 0, b = 0;
f >> a >> b;
if (type == 1)
{
tree.update(a, b);
continue;
}
g << tree.query(a, b) << '\n';
}
return 0;
}