#include <fstream>
#include <string.h>
#define MAX_DIM_TREE 262144 // 2^18 - 1
#define MAX_DIM_VECT 100000
using namespace std;
void ReadVector(int n, int* tree, istream &fin);
void Update (int node, int left, int right, int pos, int value, int* tree);
void ApplyQuerys(int m, int n, int* tree, istream& fin, ostream& fout);
int Query(int node, int left, int right, int a, int b, int *tree);
int main()
{
int tree[MAX_DIM_TREE];
memset(tree, 0, sizeof(tree));
int n, m;
ifstream fin;
ofstream fout;
fout.open("arbint.out");
fin.open("arbint.in");
fin >> n >> m;
ReadVector(n, tree, fin);
ApplyQuerys(m, n, tree, fin, fout);
fin.close();
fout.close();
return 0;
}
void ReadVector (int n, int* tree, istream &fin)
{
int x;
for(int i = 0; i < n; ++i)
{
fin >> x;
Update(1, 1, n, i + 1, x, tree);
}
}
void Update (int node, int left, int right, int pos, int value, int* tree)
{
if (left == right)
{
tree[node] = value;
return;
}
else
{
int mid = (left + right) / 2;
if (pos <= mid)
{
Update(2 * node, left, mid, pos, value, tree);
}
else
{
Update(2 * node + 1, mid + 1, right, pos, value, tree);
}
tree[node] = tree[2 * node] >= tree[2 * node + 1] ? tree[2 * node] : tree[2 * node + 1];
}
}
void ApplyQuerys(int m, int n, int* tree, istream& fin, ostream& fout)
{
int opt, a, b;
for(int i = 1; i <= m; ++i)
{
fin >> opt >> a >> b;
switch(opt)
{
case 0:
fout << Query(1, 1, n, a, b, tree) << "\n";
break;
case 1:
Update(1, 1, n, a, b, tree);
break;
default:
exit(1);
}
}
}
int Query(int node, int left, int right, int a, int b, int *tree)
{
if(a <= left && right <= b)
return tree[node];
int maxLeft, maxRight;
int mid = (left + right) / 2;
if (a <= mid)
maxLeft = Query(2 * node, left, mid, a, b, tree);
if (mid < b)
maxRight = Query(2 * node + 1, mid + 1, right, a, b, tree);
return maxLeft > maxRight ? maxLeft : maxRight;
}