#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
#include <queue>
#include <functional>
#include <bitset>
#include <set>
using namespace std;
int aint[100005 * 4];
int vec[100005];
#define left_child (nod * 2)
#define right_child (left_child | 1)
void build_tree(int nod, int left, int right) {
if (left == right) {
aint[nod] = vec[left];
return;
}
int mid = (left + right) / 2;
build_tree(left_child, left, mid);
build_tree(right_child, mid + 1, right);
aint[nod] = max(aint[left_child], aint[right_child]);
}
void update_tree(int nod, int left, int right, int pos, int value) {
if (left == right && left == pos) {
aint[nod] = value;
return;
}
int mid = (left + right) / 2;
if (pos <= mid) update_tree(left_child, left, mid, pos, value);
else update_tree(right_child, mid + 1, right, pos, value);
aint[nod] = max(aint[left_child], aint[right_child]);
}
int query_tree(int nod, int left, int right, int a, int b) {
if (a <= left && right <= b) {
return aint[nod];
}
int res = 0;
int mid = (left + right) / 2;
if (a <= mid) res = max(res, query_tree(left_child, left, mid, a, b));
if (b > mid) res = max(res, query_tree(right_child, mid + 1, right, a, b));
return res;
}
int main() {
ios::sync_with_stdio(false);
string filename = "arbint";
ifstream fin(filename + ".in");
ofstream fout(filename + ".out");
int n, m;
fin >> n >> m;
for (int i = 0; i < n; ++i)
fin >> vec[i];
build_tree(1, 0, n - 1);
while (m--) {
int typeOp, a, b;
fin >> typeOp >> a >> b;
if (typeOp == 0) fout << query_tree(1, 0, n - 1, a - 1, b - 1) << "\n";
else update_tree(1, 0, n - 1, a - 1, b);
}
//system("pause");
return 0;
}