#include <bits/stdc++.h>
std::ifstream in("arbint.in");
std::ofstream out("arbint.out");
class SEGTREE {
private:
const static int inf = (int)2e9;
int n;
std::vector<int> tree, lazy;
std::vector<bool> mark;
void push(int u, int l, int r) {
if (mark[u]) {
tree[u] = lazy[u];
if (l != r) {
lazy[2 * u] = lazy[u];
lazy[2 * u + 1] = lazy[u];
mark[2 * u] = mark[2 * u + 1] = true;
}
lazy[u] = 0;
mark[u] = false;
}
}
void build(int u, int l, int r, std::vector<int> &arr) {
if (l == r) {
tree[u] = arr[l - 1];
return;
}
int m = (l + r) / 2;
build(2 * u, l, m, arr);
build(2 * u + 1, m + 1, r, arr);
tree[u] = std::max(tree[2 * u], tree[2 * u + 1]);
}
void update(int u, int l, int r, int ql, int qr, int val) {
push(u, l, r);
if (ql > r || qr < l) {
return;
}
if (ql <= l && r <= qr) {
mark[u] = true;
lazy[u] = val;
push(u, l, r);
return;
}
int m = (l + r) / 2;
update(2 * u, l, m, ql, qr, val);
update(2 * u + 1, m + 1, r, ql, qr, val);
tree[u] = std::max(tree[2 * u], tree[2 * u + 1]);
}
int query(int u, int l, int r, int ql, int qr) {
push(u, l, r);
if (ql > r || qr < l) {
return -inf;
}
if (ql <= l && r <= qr) {
return tree[u];
}
int m = (l + r) / 2;
return std::max(query(2 * u, l, m, ql, qr), query(2 * u + 1, m + 1, r, ql, qr));
}
public:
SEGTREE(int _n) {
n = _n;
tree.resize(4 * n + 4);
mark.resize(4 * n + 4);
lazy.resize(4 * n + 4);
}
void build(std::vector<int> arr) {
build(1, 1, n, arr);
}
void update(int pos, int val) {
update(1, 1, n, pos, pos, val);
}
void update(int l, int r, int val) {
update(1, 1, n, l, r, val);
}
int query(int l, int r) {
return query(1, 1, n, l, r);
}
int query(int pos) {
return query(1, 1, n, pos, pos);
}
};
int n, m;
int main() {
in >> n >> m;
std::vector<int> v(n);
for (int &x : v) {
in >> x;
}
SEGTREE ds(n);
ds.build(v);
for (int i = 1; i <= m; i++) {
int op, x, y;
in >> op >> x >> y;
if (op == 0) {
out << ds.query(x, y) << "\n";
} else {
ds.update(x, y);
}
}
return 0;
}