//este problema arbori de intervale de pe infoarena
#include <bits/stdc++.h>
using namespace std;
ifstream fin("arbint.in");
ofstream fout("arbint.out");
int N, M;
int v[100001];
int ai[400004]; //vectorul - arbore de intervale
int qry(int st, int dr, int stcrt, int drcrt, int pozc) {
if(st == stcrt && dr == drcrt) {
return ai[pozc];
}
else {
int mij = (stcrt + drcrt) / 2;
if(dr <= mij) {
return qry(st, dr, stcrt, mij, 2*pozc);
}
if(mij+1 <= st) {
return qry(st, dr, mij+1, drcrt, 2*pozc + 1);
}
//suntem in cazul in care intra in ambele
return max(qry(st, mij, stcrt, mij, 2*pozc), qry(mij+1, dr, mij+1, drcrt, 2*pozc+1));
}
}
void upd(int st, int dr, int poz, int pozc, int val) {
if(st == dr)
ai[pozc] = val;
else {
int mij = (st + dr) / 2;
if(poz <= mij) {
//mergem in fiul din stanga
upd(st, mij, poz, 2*pozc, val);
}
else {
//mergem in fiul din dreapta
upd(mij + 1, dr, poz, 2*pozc + 1, val);
}
ai[pozc] = max(ai[2*pozc], ai[2*pozc + 1]);
}
}
int main() {
int a, b, com;
fin >> N >> M;
for(int i = 1; i <= N; i++) {
fin >> v[i];
upd(1, N, i, 1, v[i]);
}
//citim fiecare query
for(int i = 1; i <= M; i++) {
fin >> com >> a >> b;
if(com == 1) {
upd(1, N, a, 1, b);
}
else {
fout << qry(a, b, 1, N, 1) << "\n";
}
}
return 0;
}