//#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <bits/stdc++.h>
using namespace std;
template<typename T>
class LazySegmentTree {
public:
LazySegmentTree(const int _n = 0) : delta(2 * _n), tree(2 * _n), n(_n) {
for (int i = 0; i < n; i += 1) {
tree[i + n] = InitValue();
}
for (int i = n - 1; i > 0; i -= 1) {
tree[i] = Combine(tree[i << 1], tree[(i << 1) | 1]);
}
fill(delta.begin(), delta.end(), NeutralDelta());
}
LazySegmentTree(const vector<T>& values) : delta(2 * values.size()), tree(2 * values.size()), n(static_cast<int>(values.size())) {
for (int i = 0; i < n; i += 1) {
tree[i + n] = values[i];
}
for (int i = n - 1; i > 0; i -= 1) {
tree[i] = Combine(tree[i << 1], tree[(i << 1) | 1]);
}
fill(delta.begin(), delta.end(), NeutralDelta());
}
T Query(int from, int to) {
from += n;
to += n;
PushDelta(from);
PushDelta(to);
int segment_length = 1;
T res = InitValue();
while (from <= to) {
if (from & 1) {
res = Combine(res, CombineNodeWithDelta(from, segment_length));
}
if (~to & 1) {
res = Combine(CombineNodeWithDelta(to, segment_length), res);
}
from = (from + 1) >> 1;
to = (to - 1) >> 1;
segment_length <<= 1;
}
return res;
}
void Update(int from, int to, const T by) {
from += n;
to += n;
PushDelta(from);
PushDelta(to);
for (int i = from, j = to; i <= j; i = (i + 1) >> 1, j = (j - 1) >> 1) {
if (i & 1) {
delta[i] = CombineDeltas(delta[i], by);
}
if (~j & 1) {
delta[j] = CombineDeltas(delta[j], by);
}
}
for (int i = from >> 1, segment_length = 1; i > 0; i >>= 1, segment_length <<= 1) {
tree[i] = Combine(CombineNodeWithDelta(i << 1, segment_length),
CombineNodeWithDelta((i << 1) | 1, segment_length));
}
for (int i = to >> 1, segment_length = 1; i > 0; i >>= 1, segment_length <<= 1) {
tree[i] = Combine(CombineNodeWithDelta(i << 1, segment_length),
CombineNodeWithDelta((i << 1) | 1, segment_length));
}
}
private:
static T Modify(const T a, const T b) {
return b;
}
static T Combine(const T a, const T b) {
return max(a, b);
}
static T NeutralDelta() {
return -1;
}
static T InitValue() {
return 0;
}
static T CombineSegmentWithDelta(const T delta, const int segment_length) {
if (delta == NeutralDelta()) {
return NeutralDelta();
}
// int result = delta;
// for (int i = 1; i < segment_length; i += 1) result = Combine(result, delta);
// return result;
return delta;
}
static T CombineValueWithDelta(const T value, const T delta) {
if (delta == NeutralDelta()) {
return value;
}
return Modify(value, delta);
}
static T CombineDeltas(const T delta_1, const T delta_2) {
if (delta_1 == NeutralDelta()) {
return delta_2;
}
if (delta_2 == NeutralDelta()) {
return delta_1;
}
return Modify(delta_1, delta_2);
}
T CombineNodeWithDelta(const int node, const int segment_length) const {
return CombineValueWithDelta(tree[node], CombineSegmentWithDelta(delta[node], segment_length));
}
void PushDelta(int node) {
for (int d = __lg(node) - 1; d >= 0; d -= 1) {
const int where = node >> d;
tree[where >> 1] = CombineNodeWithDelta(where >> 1, 1 << (d + 1));
delta[where ^ 0] = CombineDeltas(delta[where ^ 0], delta[where >> 1]);
delta[where ^ 1] = CombineDeltas(delta[where ^ 1], delta[where >> 1]);
delta[where>> 1] = NeutralDelta();
}
}
vector<T> delta, tree;
int n;
};
int main() {
ifstream cin("arbint.in");
ofstream cout("arbint.out");
cin.tie(0);
ios_base::sync_with_stdio(false);
int n, q; cin >> n >> q;
vector<int> v(n);
for (auto& x : v) {
cin >> x;
}
LazySegmentTree<int> tree(v);
while (q--> 0) {
int type; cin >> type;
if (type == 0) {
int left, right; cin >> left >> right; left -= 1; right -= 1;
cout << tree.Query(left, right) << '\n';
} else {
int pos, value; cin >> pos >> value; pos -= 1;
tree.Update(pos, pos, value);
}
}
return 0;
}