///INTERVAL TREE
#include <fstream>
#include <vector>
#include <cstdlib>
using namespace std;
struct Node {
int val = -1;
Node* left = NULL;
Node* right = NULL;
};
void updateTree(Node* node, int A, int B, const int i, const int val) {
if(A == B) {
node -> val = val;
} else {
int M = (A+B)/2;
if(i<=M) {
if(node -> left == NULL) {
node -> left = new Node;
}
updateTree(node -> left, A, M, i, val);
} else {
if(node -> right == NULL) {
node -> right = new Node;
}
updateTree(node -> right, M+1, B, i, val);
}
if(node -> left != NULL) {
node -> val = node -> left -> val;
if(node -> right != NULL) {
node -> val = max(node -> val, node -> right -> val);
}
} else {
node -> val = node -> right -> val;
}
}
}
Node* buildTree(vector<int>& data) {
Node* root = new Node;
for(int i=0; i<data.size(); ++i) {
updateTree(root, 0, data.size()-1, i, data[i]);
}
return root;
}
int queryTree(Node* node, int A, int B, const int a, const int b) {
if(a<=A && B<=b) {
return node -> val;
} else {
int left, right;
left = right = 0;
int M = (A+B)/2;
if(a<=M) {
left = queryTree(node -> left, A, M, a, b);
}
if(M<b) {
right = queryTree(node -> right, M+1, B, a, b);
}
return max(left, right);
}
}
int main() {
ifstream fin("arbint.in");
ofstream fout("arbint.out");
int N, M;
fin >> N >> M;
vector<int> data(N);
for(int i=0; i<N; ++i) {
fin >> data[i];
}
Node* root = buildTree(data);
int q, a, b;
for(int i=0; i<M; ++i) {
fin >> q >> a >> b;
if(q == 0) {
fout << queryTree(root, 0, N-1, a-1, b-1) << '\n';
} else {
updateTree(root, 0, N-1, a-1, b);
}
}
return 0;
}