#include <fstream>
#include <algorithm>
using namespace std;
ifstream cin("arbint.in");
ofstream cout("arbint.out");
int aint[400001], n;
void buildArb(int p, int lInt, int rInt) {
if( lInt == rInt ) {
if(n){
n--;
cin>>aint[p];
}
return;
}
buildArb( p * 2, lInt, lInt + (rInt - lInt) / 2);
buildArb( p * 2 + 1, lInt + (rInt - lInt) / 2 + 1, rInt);
aint[p] = max(aint[p * 2], aint[p * 2 + 1]);
}
int mxquery(int p, int lInt, int rInt, int lExtr, int rExtr ) {
if( lExtr <= lInt && rInt <= rExtr ) {
return aint[p];
}
int mx = 0;
if((lInt <= lExtr && lExtr <= lInt + (rInt - lInt) / 2) || (lExtr <= lInt && lInt <= rExtr) || (lExtr <= lInt + (rInt - lInt) / 2 && lInt + (rInt - lInt) / 2 <= rExtr) || (lInt <= rExtr && rExtr <= lInt + (rInt - lInt) / 2))
mx = max(mx, mxquery(p * 2, lInt, lInt + (rInt - lInt) / 2, lExtr, rExtr));
if ((lInt + (rInt - lInt) / 2 + 1 <= lExtr && lExtr <= rInt) || (lExtr <= rInt && rInt <= rExtr) || (lExtr <= lInt + (rInt - lInt) / 2 + 1 && lInt + (rInt - lInt) / 2 + 1 <= rExtr) || (lInt + (rInt - lInt) / 2 + 1 <= rExtr && rExtr <= rInt))
mx = max(mx, mxquery(p * 2 + 1, lInt + (rInt - lInt) / 2 + 1, rInt, lExtr, rExtr));
return mx;
}
void update(int p, int lInt, int rInt, int dest, int val) {
if( lInt == rInt ) {
aint[p] = val;
return;
}
int mlInt = lInt + (rInt - lInt) / 2, mrInt = lInt + (rInt - lInt) / 2 + 1;
if(lInt <= dest && dest <= mlInt) {
update(p * 2, lInt, mlInt, dest, val);
} else {
update(p * 2 + 1, mrInt, rInt, dest, val);
}
aint[p] = max(aint[p * 2], aint[p * 2 + 1]);
}
int main() {
int put2, m, i, a, b, c;
cin>>n>>m;
put2 = 1;
while( put2 < n )
put2 *= 2;
buildArb(1, 1, put2);
for( i = 1; i <= m; i++ ) {
cin>>c;
cin>>a>>b;
if(c == 0) {
cout<<mxquery(1, 1, put2, a, b)<<"\n";
} else {
update(1, 1, put2, a, b);
}
}
return 0;
}