#include <iostream>
#include <fstream>
#include <algorithm>
using namespace std;
#define NMAX 1 << 19
#define left(x) ((x) << 1) //stanga unui nod
#define right(x) ((x) << 1) + 1 //dreapta unui nod
ifstream fin("arbint.in");
ofstream fout("arbint.out");
int arbint[NMAX];
void update(int nod, int left, int right, int poz, int val)
{
if( left == right){
arbint[nod] = val;
return;
}
int mid = ( left + (right - left) / 2);
if(poz <= mid){
update(left(nod), left, mid, poz, val);
}
else{
update(right(nod), mid + 1, right, poz, val);
}
arbint[nod] = max(arbint[left(nod)], arbint[right(nod)]);
}
int query(int nod, int left, int right, int a, int b)
{
if(a <= left && right <= b)
return arbint[nod];
int mid = ( left + (right - left) / 2);
int t1 = -1, t2 = -1;
if (a <= mid)
t1 = query(left(nod), left , mid, a, b);
if (b > mid) //daca are o parte in dreapta, apelez
t2 = query(right(nod), mid + 1, right , a, b);
return max(t1, t2);
}
int main() {
int n,i , m, x, y, t;
fin >> n >> m;
for (i = 1; i <= n; ++i) {
fin >> x;
update(1, 1, n, i, x);
}
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;
}