#include <stdio.h>
#include <algorithm>
class Node
{
public:
int l;
int r;
int max = 1;
Node * lChild;
Node * rChild;
Node(int lInt, int rInt)
:l(lInt), r(rInt), lChild(NULL), rChild(NULL){max = -1;};
};
int n, m,op,i;
long arr[100005] = { 0 }, a, b;
Node * root;
void makeTree(Node** node,int start,int end)
{
*node = new Node(start, end);
if (start == end) (*node)->max = arr[start];
else
{
makeTree(&(*node)->lChild, start, (start + end) / 2);
makeTree(&(*node)->rChild, (start + end) / 2 + 1, end);
}
}
void setMax(Node* node)
{
if (node->l == node->r) node->max = arr[node->l];
else
{
setMax(node->lChild);
setMax(node->rChild);
node->max = std::max(node->lChild->max, node->rChild->max);
}
}
void update(Node* node,int pos, int value)
{
if ( pos == node->l && pos == node->r) node->max = value;
else
{
if (pos > (node->l + node->r) / 2)
{
update(node->rChild, pos, value);
node->max = std::max(node->lChild->max, node->rChild->max);
}
else
{
update(node->lChild, pos, value);
node->max = std::max(node->lChild->max, node->rChild->max);
}
}
}
int getMax(Node * node,int start,int fin)
{
if (start<=node->l && fin>=node->r) return node->max ;
else if (start >= node->rChild->l) return getMax(node->rChild, start, fin);
else if (fin <= node->lChild->r) return getMax(node->lChild, start, fin);
else return std::max(getMax(node->lChild, start, node->lChild->r), getMax(node->rChild, node->rChild->l, fin));
}
int main()
{
freopen("arbint.in", "r", stdin);
freopen("arbint.out", "w", stdout);
scanf("%d%d", &n, &m);
for (i = 0; i < n; ++i) scanf("%d", &arr[i]);
makeTree(&root, 0, n - 1);
setMax(root);
for (i = 0; i < m; ++i)
{
scanf("%d%d%d",&op,&a,&b);
if (op == 0) printf("%d\n",getMax(root, a-1, b-1));
else update(root, a-1, b-1);
}
}