#include <fstream>
#include <iostream>
#include <vector>
#include <stack>
#define maximum(a,b) \
({ \
typeof(a) _a = a; \
typeof(b) _b = b; \
_a>=_b?_a:_b; \
})
using namespace std;
template<class T>
class SegmentTree
{
public:
SegmentTree()
{}
SegmentTree(const unsigned int size) :
tree(4*size+66,-1)
{}
void updateValue
(
const int nodeIndex,
const int pos,
const T& val,
int left,
int right
)
{
/*if (left == right)
{
tree[nodeIndex] = val;
}
else
{
const int div = (left+right)/2;
if (pos <= div)
updateValue((nodeIndex<<1)+1, pos, val, left, div);
else
updateValue((nodeIndex+1)<<1, pos, val, div+1, right);
tree[nodeIndex] =
maximum(tree[(nodeIndex<<1)+1], tree[(nodeIndex+1)<<1]);
}*/
int parent;
int curNodeIndex = nodeIndex;
stack<Context> st;
st.push(Context(nodeIndex, left, right));
while (!st.empty())
{
const Context ctx = st.top();
if (ctx.left == ctx.right)
{
tree[ctx.nodeIndex] = val;
curNodeIndex = ctx.nodeIndex;
break;
}
else
{
const int div = (ctx.left+ctx.right)/2;
//cout << div << endl;
if (pos <= div)
{
st.push(Context((ctx.nodeIndex<<1)+1, ctx.left, div));
}
else
{
st.push(Context((ctx.nodeIndex+1)<<1, div+1, ctx.right));
}
}
}
parent = (curNodeIndex-1-!(curNodeIndex%2))>>1;
while (parent>=0)
{
const int child1 = (parent<<1)+1;
const int child2 = (parent+1)<<1;
tree[parent] = maximum(tree[child1], tree[child2]);
curNodeIndex = parent;
parent = (curNodeIndex-1-!(curNodeIndex%2))>>1;
//cout << "Parent is " << parent << endl;
}
}
const T& queryInterval
(
const int nodeIndex,
const int start,
const int end,
const int left,
const int right
) const
{
int maxi = -1;
int indexOfMax = -1;
stack<Context> st;
st.push(Context(nodeIndex,left,right));
while (!st.empty())
{
const Context ctx = st.top();
st.pop();
if (start <= ctx.left && ctx.right <= end)
{
if (maxi < tree[ctx.nodeIndex])
{
maxi = tree[ctx.nodeIndex];
indexOfMax = ctx.nodeIndex;
}
}
else
{
const int div = (ctx.left+ctx.right)/2;
if (start <= div)
{
st.push(Context((ctx.nodeIndex<<1)+1, ctx.left, div));
}
if (div < end)
{
st.push(Context((ctx.nodeIndex+1)<<1, div+1, ctx.right));
}
}
}
return tree[indexOfMax];
}
void printTree() const
{
for (unsigned int i=0; i<tree.size(); ++i)
{
cout << tree[i] << " ";
}
cout << "\n";
}
private:
vector<T> tree;
struct Context
{
Context()
{}
Context(const int index, const int l, const int r) :
nodeIndex(index),
left(l),
right(r)
{}
int nodeIndex;
int left;
int right;
};
};
int main()
{
int n,m;
fstream fin("arbint.in", fstream::in);
fstream fout("arbint.out", fstream::out);
fin >> n >> m;
//cout << n << " " << m << endl;
SegmentTree<int> segTree(n);
for (int i=0; i<n; ++i)
{
int x;
fin >> x;
//cout << "Read " << x << " for position " << i << endl;
segTree.updateValue(0,i,x,0,n-1);
//segTree.printTree();
//cout << endl;
}
for (int i=0; i<m; ++i)
{
int op, a, b;
fin >> op >> a >> b;
switch (op)
{
case 0:
{
//cout << op << " " << a-1 << " " << b-1 << "\n";
fout << segTree.queryInterval(0, a-1, b-1, 0, n-1) << "\n";
}; break;
case 1:
{
//cout << op << " " << a-1 << " " << b << "\n";
segTree.updateValue(0,a-1,b,0,n-1);
//segTree.printTree();
}; break;
}
//cout << "\n";
}
fin.close();
fout.close();
return 0;
}