#include <fstream>
using namespace std;
ifstream fin("arbint.in");
ofstream fout("arbint.out");
const int MAXN = 1e5;
const int MAXP2 = (1 << 15);
int max(int a, int b) {
return a > b ? a : b;
}
struct SegTree {
int arr[2 * (MAXP2 + 1)];
int n;
void init(int _n, int a[MAXN]) {
int i;
/*
n = 1;
while (n < _n) {
n <<= 1;
}
*/
n = 1 << (32 - __builtin_clz(_n - 1));
for (i = 0; i < _n; ++i) {
arr[n + i] = a[i];
}
for (i = n - 1; i > 0; --i) {
arr[i] = max(arr[(i << 1)], arr[(i << 1) | 1]);
}
}
int max_query(int l, int r) {
l += n;
r += n;
int ans = -1;
while (r >= l) {
if (arr[l] > ans) ans = arr[l];
if (arr[r] > ans) ans = arr[r];
if (l & 1) ++l;
if (!(r & 1)) --r;
l >>= 1;
r >>= 1;
}
return ans;
}
void set_val(int pos, int val) {
pos += n;
arr[pos] = val;
for (pos >>= 1; pos; pos >>= 1) {
arr[pos] = max(arr[pos << 1], arr[(pos << 1) | 1]);
}
}
} aint;
int a[MAXN];
int n, m;
void citire() {
fin >> n >> m;
for (int i = 0; i < n; ++i) {
fin >> a[i];
}
}
void process_queries() {
int qt, a, b;
for (int i = 0; i < m; ++i) {
fin >> qt >> a >> b;
if (qt == 0) {
fout << aint.max_query(a - 1, b - 1) << '\n';
} else {
aint.set_val(a - 1, b);
}
}
}
int main() {
citire();
aint.init(n, a);
process_queries();
}