#include <bits/stdc++.h>
#define NM 100010
using namespace std;
ifstream fin("arbint.in");
ofstream fout("arbint.out");
int tree[4*NM], v[NM],n,m,i,t,x,y;
void build(int nod, int st, int dr) {
if(st == dr) {
tree[nod] = v[st];
return;
}
int mij = (st + dr) / 2;
build(2 * nod, st, mij);
build(2 * nod + 1, mij + 1, dr);
tree[nod] =max( tree[2 * nod] , tree[2 * nod + 1]);
}
// modifica nr. de pe pozitia pos in val
void update(int pos, int val, int nod, int st, int dr) {
// verificam daca intervalul curent e afectat de pos
if(pos < st || pos > dr) {
return;
}
// daca ne aflam in pos, modificam valuarea
if(st == dr) {
tree[nod] = val;
return;
}
// modificam recursiv fiecare jumatate
int mij = (st + dr) / 2;
update(pos, val, 2 * nod, st, mij);
update(pos, val, 2 * nod + 1, mij + 1, dr);
tree[nod] = max(tree[2 * nod] , tree[2 * nod + 1]);
}
// suma din intervalul [a, b]
int query(int a, int b, int nod, int st, int dr) {
// [st, dr] nu e inclus in [a, b]
if(st > b || dr < a) return 0;
// [st, dr] inclus in [a, b]
if(a <= st && b >= dr) return tree[nod];
int mij = (st + dr) / 2;
int s_st = query(a, b, 2 * nod, st, mij);
int s_dr = query(a, b, 2 * nod + 1, mij + 1, dr);
return max(s_st , s_dr);
}
int main()
{
fin>>n>>m;
for(i=1; i<=n; i++)
fin>>v[i];
build(1,1,n);
for(i=1; i<=m; i++)
{
fin>>t>>x>>y;
if(t==0)
fout<<query(1,1,n,x,y)<<'\n';
else
update(1,1,n,x,y);
}
return 0;
}