#include <fstream>
std::ifstream f("arbint.in");
std::ofstream g("arbint.out");
const int MAX = 1e5, INF = 0x3f3f3f3f;
void Build(int, int, int, int[], int[]);
void query(int, int, int, int, int, int&, int St[]);
void update(int, int, int, int, int, int[]);
int main() {
int N, M;
f >> N >> M;
int v[MAX + 5], St[4 * MAX + 5];
for (int i = 1; i <= N; ++i)
f >> v[i];
Build(1, 1, N, v, St);
int quest;
for (int i = 0; i < M; ++i){
f >> quest;
if (!quest) {
int a, b;
int answer = -INF;
f >> a >> b;
query(1, 1, N, a, b, answer, St);
g << answer << "\n";
}
int value, position;
if (quest == 1) {
f >> position >> value;
update(1, 1, N, position, value, St);
}
}
return 0x0;
}
void Build(int node, int left, int right, int v[], int St[]){
if(left == right)
St[node] = v[left];
else {
int mid = (left + right) / 2, leftSon = 2 * node, rightSon = leftSon + 1;
Build(leftSon, left, mid,v, St);
Build(rightSon, mid + 1, right, v, St);
St[node] = std::max(St[leftSon], St[rightSon]);
}
}
void query(int node, int left, int right, int queryL, int queryR, int& max, int St[]){
if(queryL <= left and right <= queryR)
max = std::max(max, St[node]);
else {
int mid = (left + right) / 2, leftSon = 2 * node, rightSon = leftSon + 1;
if (queryL <= mid)
query(leftSon, left, mid, queryL, queryR, max, St);
if (queryR > mid)
query(rightSon, mid + 1, right, queryL, queryR, max, St);
}
}
void update(int node, int left, int right, int pos, int val, int St[]){
if(left == right)
St[node] = val;
else {
int mid = (left + right) / 2, leftSon = 2 * node, rightSon = leftSon + 1;
if(pos <= mid)
update(leftSon, left, mid, pos, val, St);
else
update(rightSon, mid + 1, right, pos, val, St);
St[node] = std::max(St[leftSon], St[rightSon]);
}
}