#include <iostream>
#include <fstream>
using namespace std;
ifstream f("arbint.in");
ofstream g("arbint.out");
const int N_MAX = 100000;
int tree[4 * N_MAX + 5];
int V[N_MAX + 5];
void build(int node, int le, int ri) {
if(le == ri) {
tree[node] = V[le];
return;
}
int mid = (le + ri) / 2;
build(2 * node, le, mid);
build(2 * node + 1, mid + 1, ri);
tree[node] = max(tree[2 * node], tree[2 * node + 1]);
}
void update(int node, int le, int ri, int pos, int val) {
if(le == ri) {
tree[node] = val;
return;
}
int mid = (le + ri) / 2;
if(pos <= mid) {
update(2 * node, le, mid, pos, val);
} else {
update(2 * node + 1, mid + 1, ri, pos, val);
}
tree[node] = max(tree[2 * node], tree[2 * node + 1]);
}
int query(int node, int le, int ri, int x, int y) {
if(x <= le && ri <= y) {
return tree[node];
}
int mid = (le + ri) / 2;
int left_ans = INT_MIN, right_ans = INT_MIN;
if(x <= mid) {
left_ans = query(2 * node, le, mid, x, y);
}
if(y > mid) {
right_ans = query(2 * node + 1, mid + 1, ri, x, y);
}
return max(left_ans, right_ans);
}
int main() {
int N, M;
f >> N >> M;
for(int i = 1; i <= N; i++) {
f >> V[i];
}
build(1, 1, N);
for(int i = 0; i < M; i++) {
int type;
f >> type;
if(type == 0) {
int a, b;
f >> a >> b;
g << query(1, 1, N, a, b) << endl;
} else if(type == 1) {
int pos, val;
f >> pos >> val;
update(1, 1, N, pos, val);
}
}
return 0;
}