#include <stdio.h>
#include <algorithm>
class Node
{
public:
int l;
int r;
long max ;
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);
(*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;
arr[pos] = 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);
}
}
}
long 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("%ld", &arr[i]);
makeTree(&root, 0, n - 1);
for (i = 0; i < m; ++i)
{
scanf("%d%ld%ld",&op,&a,&b);
if (op == 0) printf("%ld\n",getMax(root, a-1, b-1));
else update(root, a-1, b);
}
}