#include <fstream>
#include <algorithm>
#include <climits>
using namespace std;
ifstream in("arbint.in");
ofstream out("arbint.out");
#define MAX 100000
int v[MAX], tree[4 * MAX];
int N, M;
void Update(int poz, int node = 0, int left = 0, int right = N - 1)
{
if (left == right)
{
tree[node] = v[poz];
return;
}
int mid = (left + right) / 2;
int leftc = (node << 1) + 1;
int rightc = leftc + 1;
if (poz <= mid)
{
Update(poz, leftc, left, mid);
}
else
{
Update(poz, rightc, mid + 1, right);
}
tree[node] = max(tree[leftc], tree[rightc]);
}
int Query(int x, int y, int node = 0, int left = 0, int right = N - 1)
{
if (left >= x && right <= y)
{
return tree[node];
}
int mid = (left + right) / 2;
int leftc = (node << 1) + 1;
int rightc = leftc + 1;
if (y <= mid)
{
return Query(x, y, leftc, left, mid);
}
else if (x > mid)
{
return Query(x, y, rightc, mid + 1, right);
}
else
{
return max(Query(x, y, leftc, left, mid), Query(x, y, rightc, mid + 1, right));
}
}
void BuildTree(int node = 0, int left = 0, int right = N - 1)
{
if (left == right)
{
tree[node] = v[left];
return;
}
int mid = (left + right) / 2;
int leftc = (node << 1) + 1;
int rightc = leftc + 1;
BuildTree(leftc, left, mid);
BuildTree(rightc, mid + 1, right);
tree[node] = max(tree[leftc], tree[rightc]);
}
int main()
{
in >> N >> M;
for (int i = 0; i < N; i++)
{
in >> v[i];
}
BuildTree(0, 0, N-1);
for (int i = 0; i < M; i++)
{
int opt, a, b;
in >> opt >> a >> b;
if (opt == 0)
{
out << Query(a - 1, b - 1) << endl;
}
else if (opt == 1)
{
v[a - 1] = b;
Update(a - 1);
}
}
}