#include <algorithm>
#include <fstream>
#include <vector>
using namespace std;
int answer, a[100005];
struct TreeNode {
vector<int> version, left, right, answer;
inline void insert_version(int v, int l, int r, int a) {
version.push_back(v);
left.push_back(l);
right.push_back(r);
answer.push_back(a);
}
} aint[270005];
void build(int node, int left, int right) {
aint[node].insert_version(0, 0, 0, 0);
if (left == right) {
aint[node].answer[0] = a[left];
} else {
int middle = (left + right) / 2;
build(2 * node, left, middle);
build(2 * node + 1, middle + 1, right);
aint[node].answer[0] = max(aint[2 * node].answer[0], aint[2 * node + 1].answer[0]);
}
}
int v;
void update(int node, int left, int right, int x, int y) {
if (left == right) {
aint[node].insert_version(v, 0, 0, y);
} else {
int middle = (left + right) / 2;
if (x <= middle) {
update(2 * node, left, middle, x, y);
} else {
update(2 * node + 1, middle + 1, right, x, y);
}
aint[node].version.push_back(v);
aint[node].left.push_back(aint[2 * node].version.size() - 1);
aint[node].right.push_back(aint[2 * node + 1].version.size() - 1);
aint[node].answer.push_back(max(aint[2 * node].answer.back(), aint[2 * node + 1].answer.back()));
}
}
void query(int node, int left, int right, int x, int y) {
if (x <= left && right <= y) {
answer = max(answer, aint[node].answer.back());
} else {
int middle = (left + right) / 2;
if (x <= middle) {
query(2 * node, left, middle, x, y);
}
if (y > middle) {
query(2 * node + 1, middle + 1, right, x, y);
}
}
}
int main() {
ifstream fin("arbint.in");
ofstream fout("arbint.out");
int n, m;
fin >> n >> m;
for (int i = 1; i <= n; ++ i) {
fin >> a[i];
}
build(1, 1, n);
for (int i = 1; i <= m; ++ i) {
int x, y, type;
fin >> type >> x >> y;
if (type == 1) {
++ v;
update(1, 1, n, x, y);
} else {
answer = 0;
query(1, 1, n, x, y);
fout << answer << "\n";
}
}
return 0;
}