#include <fstream>
using namespace std;
const int N = 1e5, oo = 2e9;
int a[N + 5], segm_tree[2 * N + 5];
ifstream fin ("arbint.in");
ofstream fout ("arbint.out");
int n, q;
void Read_Array ()
{
fin >> n >> q;
for (int i = 1; i <= n; i++)
fin >> a[i];
}
void Recalculate (int node)
{
segm_tree[node] = max(segm_tree[2 * node + 1], segm_tree[2 * node + 2]);
}
void Build_Segment_Tree (int node, int left, int right)
{
if (left == right)
segm_tree[node] = a[left];
else
{
int mid = (left + right) / 2;
Build_Segment_Tree(2 * node + 1, left, mid);
Build_Segment_Tree(2 * node + 2, mid + 1, right);
Recalculate(node);
}
}
void Update (int node, int left, int right, int pos, int value)
{
if (left == right)
segm_tree[node] = value;
else
{
int mid = (left + right) / 2;
if (pos <= mid)
Update (2 * node + 1, left, mid, pos, value);
else Update (2 * node + 2, mid + 1, right, pos, value);
Recalculate(node);
}
}
int Segment_Max (int node, int left, int right, int x, int y)
{
/// [x, y] = query segment
if (x <= left && right <= y)
return segm_tree[node];
int answer = -oo, mid;
mid = (left + right) / 2;
if (x <= mid)
answer = max(answer, Segment_Max (2 * node + 1, left, mid, x, y));
if (y > mid)
answer = max(answer, Segment_Max (2 * node + 2, mid + 1, right, x, y));
return answer;
}
void Process_Queries ()
{
while (q--)
{
int op, x, y;
fin >> op >> x >> y;
if (op == 1)
Update (0, 1, n, x, y);
else fout << Segment_Max (0, 1, n, x, y) << "\n";
}
fout.close();
}
int main()
{
Read_Array();
Build_Segment_Tree(0, 1, n);
Process_Queries();
return 0;
}