#include <fstream>
#include <vector>
#include <algorithm>
void build(std::vector<int> &AINT , std::vector<int>& V , int node , int left , int right )
{
if(left == right)
{
AINT[node] = V[left-1];
return;
}
int mid = (left + right) / 2;
build(AINT, V, node * 2, left, mid);
build(AINT, V, node * 2 + 1, mid + 1, right);
AINT[node] = std::max(AINT[node * 2], AINT[node * 2 + 1]);
}
void update(std::vector<int>& AINT, int node, int left, int right, int pos , int val)
{ // e 1 1 5 3 2
if (left == right)
{
AINT[node] = val;
return;
}
int mid = (left + right) / 2;
if(pos <= mid)
{
update(AINT, node * 2, left, mid, pos, val);
}else
{
update(AINT, node * 2 + 1, mid + 1, right, pos, val);
}
AINT[node] = std::max(AINT[node * 2], AINT[node * 2 + 1]);
}
int query(std::vector<int>& AINT, int node, int left, int right, int q_left,int q_right)
{
if (q_left <= left && q_right >= right)
{
return AINT[node];
}
int mid = (left + right) / 2;
if(q_right <= mid)
{
return query(AINT, node * 2, left, mid, q_left, q_right);
}
if(q_left >= mid+1)
{
return query(AINT, node * 2, mid + 1, right, q_left, q_right);
}
return std::max(query(AINT, node * 2, left, mid, q_left, q_right), query(AINT, node * 2 + 1, mid + 1, right, q_left, q_right));
}
int main()
{
std::ifstream fin("arbint.in");
std::ofstream fout("arbint.out");
int n, m;
fin >> n >> m;
std::vector<int> V, AINT(n*4, 0);
for (int i = 0; i < n; i++)
{
int t;
fin >> t;
V.push_back(t);
}
build(AINT, V, 1, 1, n );
for(int i = 0; i < m ; i++)
{
int op;
fin >> op;
switch(op)
{
case 0:
int q_left, q_right;
fin >> q_left >> q_right;
fout << query(AINT, 1, 1, n, q_left, q_right) << std::endl;
break;
case 1:
int pos, val;
fin >> pos >> val;
update(AINT, 1, 1, n, pos, val);
}
}
return 0;
}