#include <bits/stdc++.h>
using namespace std;
ifstream fin ("arbint.in");
ofstream fout ("arbint.out");
struct arbore {
arbore* left;
arbore* right;
int val;
};
//TODO: De facut lazy update mai incolo
// Doar bagi var lazy daca ai bagat tot nodul in intervalul de update
vector<int> v;
void init(arbore* a, int st, int dr) {
if(st==dr) {
a->val = v[st];
return;
}
int mij = (st+dr)/2;
arbore* left = new arbore;
arbore* right = new arbore;
a->left = left;
a->right = right;
init(left, st, mij);
init(right, mij+1, dr);
a->val = max(left->val, right->val);
}
int query(arbore* a, int st, int dr, int x, int y) {
if(st>=x && dr<=y)
return a->val;
if(st==dr)
return a->val;
int mij = (st+dr)/2;
int suma = 0;
if(x <= mij)
suma = max(suma, query(a->left, st, mij, x, y));
if(mij + 1 <= y)
suma = max(suma, query(a->right, mij + 1, dr, x, y));
return suma;
}
void update(arbore* a, int poz, int val, int st, int dr) {
if(st==dr) {
a->val = val;
return;
}
int mij = (st+dr)/2;
if(poz <= mij)
update(a->left, poz, val, st, mij);
else
update(a->right, poz, val, mij+1, dr);
a->val = max(a->left->val, a->right->val);
}
int main() {
int n,m;
fin>>n>>m;
v.push_back(0);
for(int i=1; i<=n; i++) {
int a;
fin>>a;
v.push_back(a);
}
arbore* baza = new arbore;
init(baza, 1, n);
for(int i=1; i<=m; i++) {
int oper,a,b;
fin>>oper>>a>>b;
if(oper==0)
fout<<query(baza, 1, n, a, b)<<'\n';
else update(baza, a, b, 1, n);
}
}