#include <stdio.h>
#include <algorithm>
using namespace std;
FILE* fin;
FILE* fout;
struct nod
{
int Min;
int Max;
int value;
nod *st;
nod *dr;
} *vf;
nod* createTree(int Min, int Max)
{
if(Min < Max)
{
int mij = (Min + Max) / 2;
nod *q = new nod;
q->Max = Max;
q->Min = Min;
q->value = 0;
q->st = createTree(Min, mij);
q->dr = createTree(mij + 1, Max);
return q;
}
if(Min == Max)
{
nod *q = new nod;
q->Max = Max;
q->Min = Min;
q->value = 0;
q->st = nullptr;
q->dr = nullptr;
return q;
}
return nullptr;
}
void insertInTree(nod *q, int x, int pos)
{
if(q->Min == pos && q->Max == pos)
q->value = x;
else if(q->Min > pos || q->Max < pos)
return;
else{
insertInTree(q->st, x, pos);
insertInTree(q->dr, x, pos);
q->value = max(q->st->value, q->dr->value);
}
}
int queryTree(nod *q, int left, int right, int Min, int Max)
{
if(left > Max || right < Min)
return 0;
if(left >= Min && right <= Max)
return q->value;
int mid = (left + right) / 2;
return max(queryTree(q->st, q->Min, mid, Min, Max), queryTree(q->dr, mid + 1, q->Max, Min, Max));
}
void update(nod* q, int x, int pos)
{
if(q->Min == pos && q->Max == pos)
q->value = x;
else if(q->Min > pos || q->Max < pos)
return;
else{
update(q->st, x, pos);
update(q->dr, x, pos);
q->value = max(q->st->value, q->dr->value);
}
}
int main()
{
fin = fopen("arbint.in", "r");
fout = fopen("arbint.out", "w");
int V[100000];
int n, m;
fscanf(fin, "%d%d", &n, &m);
vf = createTree(1, n);
for(int i = 0; i < n; ++i)
{
fscanf(fin, "%d", V + i);
insertInTree(vf, V[i], i + 1);
}
int op, a, b;
for(int i = 0; i < m; ++i)
{
fscanf(fin, "%d%d%d", &op, &a, &b);
if(op)
{
V[a] = b;
update(vf, b, a);
}
else
fprintf(fout, "%d\n", queryTree(vf, 1, n, a, b));
}
return 0;
}