#include <fstream>
using namespace std;
const int kMaxN = 1e5+5;
// Simple and fast segment tree implementation
// The fastest solution to implement for a SIMPLE segment tree
// mx[node] = max(mx[2 * node], mx[2 * node + 1]);
//
// return max(
// query(2 * node, left, mid, c1, c2),
// query(2 * node + 1, mid + 1, right, c1, c2)
// );
// The logic is duplicated and can cause bugs when changing something
// Sometimes the logic can be very difficult (a lot of operations)
//
// Why a struct?
// - it keeps all the logic in one place.
// all segment tree related logic is easy to mentain and check
// - with time, this code will become "standard"
// the majority of the code for the segment tree will be the same every time
// in this way, it's easy to implement the same segment tree which will be "safe"
// meaning that it's highly improbable to have bugs or undefined behaviours
struct Aint {
// 3 * kMaxN is weirdly enough :)
int mx[3 * kMaxN];
// Simple single element update
void update(int node, int left, int right, int pos, int value) {
// Stop condition
if (left == right) {
mx[node] = value;
return;
}
// Advance into the recursion
int mid = (left + right) / 2;
if (pos <= mid) {
update(2 * node, left, mid, pos, value);
} else {
update(2 * node + 1, mid + 1, right, pos, value);
}
// Make sure the data from the node is correctly computed
mx[node] = max(mx[2 * node], mx[2 * node + 1]);
}
int query(int node, int left, int right, int c1, int c2) {
// The [left, right] is inside c1 and c2
// Return the data or update the inverval in case of lazy propagation
if (c1 <= left and right <= c2) {
return mx[node];
}
// The interval is outside [c1, c2]. No need to go further.
if (right < c1 or c2 < left) {
return 0;
}
// Return the max of the 2 recursive calls
int mid = (left + right) / 2;
return max(
query(2 * node, left, mid, c1, c2),
query(2 * node + 1, mid + 1, right, c1, c2)
);
}
};
int main() {
ifstream cin("arbint.in");
ofstream cout("arbint.out");
int n, q; cin >> n >> q;
Aint aint;
for (int i = 1; i <= n; i += 1) {
int x; cin >> x;
aint.update(1, 1, n, i, x);
}
while (q--) {
char c; cin >> c;
if (c == '0') {
int a, b; cin >> a >> b;
cout << aint.query(1, 1, n, a, b) << '\n';
} else {
int pos, x; cin >> pos >> x;
aint.update(1, 1, n, pos, x);
}
}
return 0;
}