#include <bits/stdc++.h>
using namespace std;
struct Node
{
uint_fast32_t maximum;
void set(uint_fast32_t value)
{
this->maximum = value;
}
void update(Node& l_child, Node& r_child)
{
this->maximum = max(l_child.maximum, r_child.maximum);
}
};
class SegmentTree
{
uint_fast32_t size;
vector<Node> segment_tree;
void build(vector<uint_fast32_t>& data, uint_fast32_t left, uint_fast32_t right, uint_fast32_t node_id)
{
if(left == right)
{
segment_tree[node_id].set(data[left]);
return;
}
uint_fast32_t l_child_id = 2 * node_id;
uint_fast32_t r_child_id = 2 * node_id + 1;
uint_fast32_t middle = (left + right) / 2;
build(data, left, middle, l_child_id);
build(data, middle + 1, right, r_child_id);
segment_tree[node_id].update(segment_tree[l_child_id], segment_tree[r_child_id]);
}
void __update(uint_fast32_t index, uint_fast32_t value, uint_fast32_t left, uint_fast32_t right, uint_fast32_t node_id)
{
if(left == right)
{
segment_tree[node_id].set(value);
return;
}
uint_fast32_t l_child_id = 2 * node_id;
uint_fast32_t r_child_id = 2 * node_id + 1;
uint_fast32_t middle = (left + right) / 2;
if(index <= middle)
{
__update(index, value, left, middle, l_child_id);
}
else
{
__update(index, value, middle + 1, right, r_child_id);
}
segment_tree[node_id].update(segment_tree[l_child_id], segment_tree[r_child_id]);
}
uint_fast32_t __query(uint_fast32_t a, uint_fast32_t b, uint_fast32_t left, uint_fast32_t right, uint_fast32_t node_id)
{
if(a <= left && right <= b)
{
return segment_tree[node_id].maximum;
}
uint_fast32_t l_child_id = 2 * node_id;
uint_fast32_t r_child_id = 2 * node_id + 1;
uint_fast32_t middle = (left + right) / 2;
uint_fast32_t answer = 0;
if(a <= middle)
{
answer = __query(a, b, left, middle, l_child_id);
}
if(b > middle)
{
answer = max(answer, __query(a, b, middle + 1, right, r_child_id));
}
return answer;
}
public:
SegmentTree(vector<uint_fast32_t>& data)
{
this->size = data.size() - 1;
segment_tree.resize(4 * this->size + 5);
build(data, 1, this->size, 1);
}
void update(uint_fast32_t index, uint_fast32_t value)
{
__update(index, value, 1, this->size, 1);
}
uint_fast32_t query(uint_fast32_t a, uint_fast32_t b)
{
return __query(a, b, 1, this->size, 1);
}
};
int main()
{
ifstream fin{"arbint.in"};
ofstream fout{"arbint.out"};
uint_fast32_t N, M;
fin >> N >> M;
vector<uint_fast32_t> data(N + 1);
for(uint_fast32_t i = 1; i <= N; ++i)
{
fin >> data[i];
}
SegmentTree segment_tree(data);
for(uint_fast32_t i = 1; i <= M; ++i)
{
uint_fast32_t type, a, b;
fin >> type >> a >> b;
if(type == 1)
{
segment_tree.update(a, b);
}
else
{
fout << segment_tree.query(a, b) << '\n';
}
}
}