#include <cstdio>
#include <cassert>
#include <algorithm>
#include <iostream>
struct ArbInt {
int size;
int max;
ArbInt *left;
ArbInt *right;
};
ArbInt* emptyArb = nullptr;
ArbInt* addNode(ArbInt* arbInt, int add) {
return new ArbInt{
arbInt->size,
arbInt->max,
arbInt->left, arbInt->right};
// *arbInt = ArbInt{
// arbInt->size,
// arbInt->max,
// arbInt->left, arbInt->right};
// return arbInt;
}
ArbInt* join(ArbInt* left, ArbInt* right) {
return new ArbInt{
left->size + right->size,
std::max(left->max, right->max),
left, right};
}
ArbInt* morpheNode(ArbInt* arbInt, ArbInt* left, ArbInt* right) {
return new ArbInt{
left->size + right->size,
std::max(left->max, right->max),
left, right};
//*arbInt = ArbInt{
// left->size + right->size,
// std::max(left->max, right->max),
// left, right};
//return arbInt;
}
//arbInt has empty sons
ArbInt* morpheNode(ArbInt* arbInt, int value) {
return new ArbInt{
arbInt->size,
value,
arbInt->left, arbInt->right};
//*arbInt = ArbInt{
// arbInt->size,
// arbInt->max + value,
// arbInt->left, arbInt->right};
//return arbInt;
}
ArbInt* build(int* begin, int* end) {
int size = end - begin;
assert(0 < size);
if (size == 1)
return new ArbInt{size, *begin, emptyArb, emptyArb};
else {
int half = size / 2;
ArbInt* arbLeft = build(begin, begin + half);
ArbInt* arbRight = build(begin + half, end);
return join(arbLeft, arbRight);
}
}
ArbInt* update(ArbInt* arbInt, int i, int value) {
assert(arbInt != emptyArb && 0 <= i && i < arbInt->size);
if (arbInt->size == 1)
return morpheNode(arbInt, value);
else if (i < arbInt->left->size)
return morpheNode(arbInt,
update(arbInt->left, i, value),
arbInt->right);
else
return morpheNode(arbInt,
arbInt->left,
update(arbInt->right, i - arbInt->left->size, value));
}
ArbInt* query(ArbInt* arbInt, int from, int to) {
// printf("%d %d %d\n", arbInt->size, from, to);
// fflush(stdout);
assert(arbInt != emptyArb && 0 <= from && from <= to && to < arbInt->size);
if (from == 0 && to == arbInt->size - 1)
return arbInt;
else if (to < arbInt->left->size)
return query(arbInt->left, from, to);
else if (arbInt->left->size <= from)
return query(arbInt->right, from - arbInt->left->size, to - arbInt->left->size);
else
return join(
query(arbInt->left, from, arbInt->left->size - 1),
query(arbInt->right, 0, to - arbInt->left->size));
}
void dump(ArbInt* arbInt, int depth = 0) {
if (arbInt != emptyArb) {
dump(arbInt->left, depth + 1);
for (int i = 0; i < depth; i++) {
printf(" ");
}
printf("%1d %2d\n", arbInt->size, arbInt->max);
dump(arbInt->right, depth + 1);
}
}
int main() {
freopen("arbint.in", "r", stdin);
freopen("arbint.out", "w", stdout);
int N, M;
scanf("%d%d", &N, &M);
int* V = new int[N];
for (int i = 0; i < N; i++)
scanf("%d", &V[i]);
// fa ceva cu V
ArbInt* arbInt = build(V, V + N);
// dump(arbInt, 0);
// std::cout<<std::endl;
for (int i = 0; i < M; i++) {
int op, a, b;
scanf("%d%d%d", &op, &a, &b);
if (op == 0) { // query
int answer = query(arbInt, a - 1, b - 1)->max;
printf("%d\n", answer);
} else { // update
arbInt = update(arbInt, a - 1, b);
// dump(arbInt, 0);
// std::cout<<std::endl;
}
}
return 0;
}