#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <climits> // Include biblioteca pentru INT_MIN
using namespace std;
class SegmentTree {
public:
SegmentTree(const vector<int>& data) {
n = data.size();
tree.resize(4 * n);
build(data, 0, 0, n - 1);
}
int query(int l, int r) {
return query(0, 0, n - 1, l, r);
}
void update(int idx, int value) {
update(0, 0, n - 1, idx, value);
}
private:
vector<int> tree;
int n;
void build(const vector<int>& data, int node, int start, int end) {
if (start == end) {
tree[node] = data[start];
} else {
int mid = (start + end) / 2;
build(data, 2 * node + 1, start, mid);
build(data, 2 * node + 2, mid + 1, end);
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 || l > end) {
return INT_MIN; // Asigură-te că ai inclus <climits>
}
if (l <= start && r >= end) {
return tree[node];
}
int mid = (start + end) / 2;
int left_query = query(2 * node + 1, start, mid, l, r);
int right_query = query(2 * node + 2, mid + 1, end, l, r);
return max(left_query, right_query);
}
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 main() {
ifstream infile("arbint.in");
ofstream outfile("arbint.out");
int N, M;
infile >> N >> M;
vector<int> data(N);
for (int i = 0; i < N; ++i) {
infile >> data[i];
}
SegmentTree segTree(data);
for (int i = 0; i < M; ++i) {
int op, a, b;
infile >> op >> a >> b;
if (op == 0) {
outfile << segTree.query(a - 1, b - 1) << endl;
} else if (op == 1) {
segTree.update(a - 1, b);
}
}
infile.close();
outfile.close();
return 0;
}