#include <cstdio>
#include <algorithm>
#include <cmath>
std::vector<int> val;
#define DIM 666013
char buffer[DIM];
int poz = DIM - 1;
void read(int &A)
{
A = 0;
while('0' > buffer[poz] || buffer[poz] > '9')
if(++poz == DIM) fread(buffer,1,DIM,stdin),poz = 0;
while('0' <= buffer[poz] && buffer[poz] <= '9')
{
A = A * 10 + buffer[poz] - 48;
if(++poz == DIM) fread(buffer,1,DIM,stdin),poz = 0;
}
}
class SegmentTree{
private:
std::vector<int> aint;
public:
SegmentTree(){}
SegmentTree(int k){
aint.resize(1<<((int)ceil(log2((double)k))+1));
}
void resizeSTree(int k){
aint.resize(1<<((int)ceil(log2((double)k))+1));
}
void query(int li,int lf,int pz,int &A,int &B, int &answer)
{
if(A <= li && lf <= B){
answer = std::max(answer,aint[pz]);
return;
}
int m = li + ((lf - li) >> 1);
if(A <= m) query(li, m, pz << 1, A, B, answer);
if(m < B) query(m + 1, lf, (pz << 1) | 1, A, B, answer);
}
void update(int li,int lf, int pz, int &pos, int &_newX)
{
if(li == lf){
aint[pz] = _newX;
return;
}
int m = li + ((lf - li) >> 1);
if(pos <= m) update(li, m, pz << 1, pos, _newX);
else update(m + 1, lf, (pz << 1) | 1, pos, _newX);
aint[pz] = std::max(aint[pz << 1], aint[(pz << 1) | 1]);
}
void build(int li,int lf,int pz)
{
if(li == lf){
aint[pz] = val[li];
return;
}
int m = li + ((lf - li) >> 1);
build(li, m, pz << 1);
build(m + 1, lf, (pz << 1) | 1);
aint[pz] = std::max(aint[pz << 1], aint[(pz << 1) | 1]);
}
};
SegmentTree STree;
int N,M;
void read()
{
read(N);read(M);
val.resize(N + 1);
STree.resizeSTree(N);
for(int i = 1; i <= N; ++i)
read(val[i]);
STree.build(1,N,1);
}
void solve()
{
const int INF = 0x3f3f3f3f;
int op,a,b,answer;
for(int i = 1; i <= M; ++i)
{
read(op);read(a);read(b);
if(op == 0){
answer = -INF;
STree.query(1,N,1,a,b,answer);
printf("%d\n",answer);
continue;
}
STree.update(1,N,1,a,b);
}
}
int main()
{
freopen("arbint.in","r",stdin);
freopen("arbint.out","w",stdout);
read();
solve();
return 0;
}