#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <climits>
using namespace std;
class SegmentTree {
private:
vector<int> tree;
int size;
void build(const vector<int>& arr, int node, int start, int end) {
if (start == end) {
tree[node] = arr[start];
} else {
int mid = (start + end) / 2;
build(arr, 2 * node + 1, start, mid);
build(arr, 2 * node + 2, mid + 1, end);
tree[node] = max(tree[2 * node + 1], tree[2 * node + 2]);
}
}
void update(int node, int start, int end, int idx, int value) {
if (start == end) {
tree[node] = value;
} else {
int mid = (start + end) / 2;
if (idx <= mid) {
update(2 * node + 1, start, mid, idx, value);
} else {
update(2 * node + 2, mid + 1, end, idx, value);
}
tree[node] = max(tree[2 * node + 1], tree[2 * node + 2]);
}
}
int query(int node, int start, int end, int L, int R) {
if (R < start || end < L) {
return INT_MIN;
}
if (L <= start && end <= R) {
return tree[node];
}
int mid = (start + end) / 2;
int leftMax = query(2 * node + 1, start, mid, L, R);
int rightMax = query(2 * node + 2, mid + 1, end, L, R);
return max(leftMax, rightMax);
}
public:
SegmentTree(const vector<int>& arr) {
size = arr.size();
tree.resize(4 * size);
build(arr, 0, 0, size - 1);
}
void update(int idx, int value) {
update(0, 0, size - 1, idx, value);
}
int query(int L, int R) {
return query(0, 0, size - 1, L, R);
}
};
int main() {
ifstream fin("arbint.in");
ofstream fout("arbint.out");
int N, M;
fin >> N >> M;
vector<int> arr(N);
for (int i = 0; i < N; ++i) {
fin >> arr[i];
}
SegmentTree segTree(arr);
for (int i = 0; i < M; ++i) {
int type, a, b;
fin >> type >> a >> b;
if (type == 0) {
fout << segTree.query(a - 1, b - 1) << endl;
} else if (type == 1) {
segTree.update(a - 1, b);
}
}
fin.close();
fout.close();
return 0;
}