#include <bits/stdc++.h>
#include <random>
#include <chrono>
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
const char nl = '\n';
const char sp = ' ';
const int inf = 0x3f3f3f3f;
const long long INF = 1000000000000000000;
const int mod = 1e9 + 7;
const char out[2][4]{ "NO", "YES" };
#define all(a) a.begin(), a.end()
using ll = long long;
ifstream fin("arbint.in");
ofstream fout("arbint.out");
#define variableName(var) #var
#define __debug(var) cout << #var << " = " << var << '\n'
inline int rint(int a, int b) { return uniform_int_distribution<int>(a, b)(rng); }
struct TreeNode {
TreeNode* left, * right;
int value;
TreeNode() {
value = 0;
left = nullptr;
right = nullptr;
}
void propagate() {
if (left == nullptr) {
left = new TreeNode;
}
if (right == nullptr) {
right = new TreeNode;
}
}
void update() {
value = max(right->value, left->value);
}
};
void update(TreeNode* root, int l, int r, int pos, int val) {
if (l > pos || r < pos) {
return;
}
if (l == r) {
root->value = val;
return;
}
root->propagate();
int mid = (l + r) / 2;
update(root->left, l, mid, pos, val);
update(root->right, mid + 1, r, pos, val);
root->update();
}
int query(TreeNode* root, int l, int r, int ql, int qr) {
if (l > qr || r < ql) {
return 0;
}
if (ql <= l && r <= qr) {
return root->value;
}
root->propagate();
int mid = (l + r) / 2;
return max(query(root->left, l, mid, ql, qr),
query(root->right, mid + 1, r, ql, qr));
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int n, q;
fin >> n >> q;
TreeNode* aint = new TreeNode;
for (int i = 1; i <= n; ++i) {
int x;
fin >> x;
update(aint, 1, n, i, x);
}
while (q--) {
int t, a, b;
fin >> t >> a >> b;
if (t == 0) {
fout << query(aint, 1, n, a, b) << nl;
}
else {
update(aint, 1, n, a, b);
}
}
}