#include <algorithm>
#include <fstream>
#include <vector>
using namespace std;
const int MAX_N = 100005;
int answer;
int v, a[MAX_N];
struct TreeNode {
TreeNode *left, *right;
int value;
} *root[MAX_N];
void build(TreeNode* &node, int left, int right) {
node = new TreeNode();
if (left == right) {
node->value = a[left];
} else {
int middle = (left + right) / 2;
build(node->left, left, middle);
build(node->right, middle + 1, right);
node->value = max(node->left->value, node->right->value);
}
}
void update(TreeNode* &next_node, TreeNode* &anterior, int left, int right, int x, int y) {
next_node = new TreeNode();
if (left == right) {
next_node->value = y;
} else {
next_node->left = anterior->left;
next_node->right = anterior->right;
int middle = (left + right) / 2;
if (x <= middle) {
update(next_node->left, anterior->left, left, middle, x, y);
} else {
update(next_node->right, anterior->right, middle + 1, right, x, y);
}
next_node->value = max(next_node->left->value, next_node->right->value);
}
}
void query(TreeNode* &node, int left, int right, int x, int y) {
if (x <= left && right <= y) {
answer = max(answer, node->value);
} else {
int middle = (left + right) / 2;
if (x <= middle) {
query(node->left, left, middle, x, y);
}
if (y > middle) {
query(node->right, 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(root[0], 1, n);
for (int i = 1; i <= m; ++ i) {
int type, x, y;
fin >> type >> x >> y;
if (type == 1) {
++ v;
update(root[v], root[v - 1], 1, n, x, y);
} else {
answer = 0;
query(root[v], 1, n, x, y);
fout << answer << "\n";
}
}
return 0;
}