#include <fstream>
#include <vector>
using namespace std;
ifstream f("arbint.in");
ofstream g("arbint.out");
class SegmentTree
{
int n;
vector<int> t;
void go(const int node, const int left, const int right, const vector<int> &v)
{
if (left > right)
return;
if (left == right)
{
t[node] = v[(left - 1)];
return;
}
int mid = ((left + right) >> 1);
go((node << 1), left, mid, v),
go(((node << 1) + 1), (mid + 1), right, v);
t[node] = max(t[(node << 1)], t[((node << 1) + 1)]);
return;
}
void update(const int node, const int left, const int right, const int pos, const int x)
{
if (left > right)
return;
if (left == right)
{
t[node] = x;
return;
}
int mid = ((left + right) >> 1);
if (pos <= mid)
update((node << 1), left, mid, pos, x);
else
update(((node << 1) + 1), (mid + 1), right, pos, x);
t[node] = 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 <= a && b <= qb)
return t[node];
int mid = ((a + b) >> 1);
int p_left = 0, p_right = 0;
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 max(p_left, p_right);
}
public:
SegmentTree(const vector<int> &v)
{
n = (int)v.size();
t = vector<int>((n << 2) + 4);
go(1, 1, n, v);
}
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> v(n);
for (int i = 0; i < n; ++i)
f >> v[i];
SegmentTree T(v);
for (int i = 0; i < m; ++i)
{
short int type = 0;
int a = 0, b = 0;
f >> type >> a >> b;
if (type == 0)
g << T.query(a, b) << '\n';
else
T.update(a, b);
}
return 0;
}