# include <iostream>
# include <vector>
# include <cstdio>
using namespace std;
class SegmentTree{
private :
int sz;
vector<int> t;
public :
SegmentTree(int n) {
sz = n;
t.resize(4*sz);
}
SegmentTree(int n, int a[]) {
sz = n;
t.resize(4*sz);
Build(a);
}
void __build(int nod, int nl ,int nr, int a[])
{
if (nl == nr) t[nod] = a[nl];
else {
int md = (nl + nr) >> 1;
__build(nod + nod, nl, md,a);
__build(nod + nod + 1, md + 1, nr,a);
t[nod] = max(t[nod + nod], t[nod + nod + 1]);
}
}
void Build(int a[])
{
__build(1,1,sz,a);
}
int __Max(int nod, int nl ,int nr, int l, int r)
{
if (nl == l && nr == r) return t[nod];
int md = (nl+nr)>>1;
if (r<=md) return __Max(nod + nod, nl, md, l,r);
if (l>md) return __Max(nod + nod +1 , md + 1, nr, l , r);
return max (
__Max(nod + nod, nl, md, l, md),
__Max(nod + nod + 1, md + 1, nr, md + 1, r)
);
}
int GetMaxInRange(int left, int right) {
return __Max(1,1,sz,left,right);
}
void __update(int nod ,int nl, int nr, int pos , int val)
{
if (nl == nr) {
t[nod] = val;
return;
}
int md = ( nl + nr ) >> 1;
if (pos <= md) __update(nod + nod, nl, md, pos, val);
else __update(nod + nod + 1, md + 1, nr, pos, val);
t[nod ] =max(t[nod + nod], t[nod + nod + 1]);
}
void UpdateElementAtPos(int pos, int val)
{
__update(1,1,sz,pos, val);
}
};
int a[1000005];
int main() {
freopen("arbint.in","r",stdin);
freopen("arbint.out","w",stdout);
int n , m;
cin >> n >> m;
for(int i = 1; i <= n; ++i) {
cin >> a[i];
}
SegmentTree SG(n);
SG.Build(a);
while (m--) {
int type;
scanf("%d", &type);
if (type == 0) {
int left, right;
scanf("%d%d", &left, &right);
printf("%d\n",SG.GetMaxInRange(left, right));
}
if (type == 1) {
int pos, val;
scanf("%d%d", &pos, &val);
SG.UpdateElementAtPos(pos,val);
}
}
return 0;
}