// Arbori intervale - O(logN) pe operatie
#include <fstream>
#define Nmax 100099
#define oo 2000000000
using namespace std;
ifstream f("arbint.in");
ofstream g("arbint.out");
int N, M, v[Nmax], MAX[4*Nmax];
// node [st, dr]
// cand vreau sa fac ceva cu intervalul [A, B]
void upd(int node, int st, int dr, int A, int B, int val) {
if (st == dr){
MAX[node] = val;
//MIN[node] = val;
return;
}
int mij = (st+dr) / 2 , s1 = 2 * node, s2 = 2 * node + 1;
if(A <= mij)upd(s1, st, mij, A, B, val);
else upd(s2, mij+1, dr, A, B, val);
if(MAX[s1] > MAX[s2]) MAX[node] = MAX[s1];
else MAX[node] = MAX[s2];
/*
if(MIN[s1] < MIN[s2]) MIN[node] = MIN[s1];
else MIN[node] = MIN[s2];
*/
}
int query(int node, int st, int dr, int A, int B) {
if(A <= st && dr <= B) {
return MAX[node];
}
int sol1 = 0, sol2 = 0;
int mij = (st + dr) / 2 , s1 = 2 * node, s2 = 2 * node +1;
if(A <= mij) sol1 = query(s1, st, mij, A, B);
if(mij < B) sol2 = query(s2, mij + 1, dr, A, B);
return max(sol1, sol2);
}
int main() {
f >> N >> M;
/* init */
for(int i = 1; i <= N; ++i) {
int val;
f>>val;
// nod 1 [1, N] - v[i] = val -> [i, i]
upd(1, 1, N, i, i, val);
}
for(int j=1;j<=M;++j) {
int x, y, op, i , val;
f >> op;
if(op == 1) {
f >> i >> val;
upd(1, 1, N, i, i, val);
}
else {
int A, B;
f >> A >> B;
g << query(1, 1, N, A, B) << '\n';
}
}
f.close();g.close();
return 0;
}