#include <array>
#include <cstdint>
#include <fstream>
#include <vector>
using u32 = uint32_t;
constexpr size_t MAX_NODES = 100000;
std::array<u32, MAX_NODES * 4> arbint;
std::array<u32, MAX_NODES> ogValues;
size_t LEFT (size_t node) { return node * 2 + 1; }
size_t RIGHT (size_t node) { return node * 2 + 2; }
size_t MIJ (size_t lhs, size_t rhs) { return lhs + (rhs - lhs) / 2; }
void build (size_t node, size_t intLeft, size_t intRight) {
if (intLeft == intRight - 1) {
arbint[node] = ogValues[intLeft];
return;
}
const size_t mij = MIJ(intLeft, intRight);
build(LEFT(node), intLeft, mij);
build(RIGHT(node), mij, intRight);
arbint[node] = std::max(arbint[LEFT(node)], arbint[RIGHT(node)]);
}
void update (size_t index, u32 value, size_t node, size_t intLeft, size_t intRight) {
if (intRight - 1 == intLeft && intLeft == index) {
arbint[node] = value;
return;
}
const size_t mij = MIJ(intLeft, intRight);
if (index < mij)
update(index, value, LEFT(node), intLeft, mij);
else
update(index, value, RIGHT(node), mij, intRight);
arbint[node] = std::max(arbint[LEFT(node)], arbint[RIGHT(node)]);
}
u32 query (size_t left, size_t right, size_t node, size_t intLeft, size_t intRight) {
if (left <= intLeft && intRight <= right)
return arbint[node];
if (left >= intRight || right <= intLeft)
return 0;
const size_t mij = MIJ(intLeft, intRight);
u32 max = 0;
if (left < mij)
max = std::max(max, query(left, right, LEFT(node), intLeft, mij));
if (mij < right)
max = std::max(max, query(left, right, RIGHT(node), mij, intRight));
return max;
}
void debugArbint (size_t node, size_t intLeft, size_t intRight) {
if (intLeft >= intRight)
return;
std::fprintf(stderr, "For [%zu, %zu) I have associated maximum: %u\n", intLeft, intRight, arbint[node]);
if (intLeft != intRight - 1) {
const size_t mij = MIJ(intLeft, intRight);
debugArbint(LEFT(node), intLeft, mij);
debugArbint(RIGHT(node), mij, intRight);
}
}
int main () {
std::ifstream in("arbint.in");
std::ofstream out("arbint.out");
size_t numberCount, queryCount;
in >> numberCount >> queryCount;
for (size_t i = 0; i != numberCount; ++ i)
in >> ogValues[i];
build(0, 0, numberCount);
for (size_t i = 0; i != queryCount; ++ i) {
u32 type;
in >> type;
if (type == 0) {
size_t left, right;
in >> left >> right;
-- left, -- right;
out << query(left, right + 1, 0, 0, numberCount);
out.put('\n');
} else {
size_t index;
u32 newValue;
in >> index >> newValue;
-- index;
update(index, newValue, 0, 0, numberCount);
}
}
}