#include <vector>
#include <utility>
#include <cstdlib>
template<typename T, typename TFunc>
class IntervalTree
{
private:
struct Node
{
size_t a, b;
Node *parent, *left, *right;
T val;
};
public:
IntervalTree(const std::vector<T>& _cont, TFunc _functor) :
functor(std::move(_functor)),
initialCont(&_cont),
root(nullptr),
leaves(_cont.size(), nullptr)
{
ConstructTree(0, _cont.size() - 1, &root);
initialCont = nullptr;
}
~IntervalTree()
{
DestructDownwards(&root);
}
void UpdateValue(size_t index, const T& val)
{
leaves[index]->val = val;
UpdateUpwards(leaves[index]);
}
void GetRange(size_t a, size_t b, T** out)
{
if ((a <= b) && (b < leaves.size()))
{
(*out) = new T(GetRange(leaves[a], a, b));
}
else
{
(*out) = nullptr;
}
}
private:
void ConstructTree(const size_t a, const size_t b, Node** node)
{
if (a <= b)
{
(*node) = new Node;
(*node)->parent = (*node)->right = (*node)->left = nullptr;
(*node)->a = a;
(*node)->b = b;
if (a == b)
{
(*node)->val = (*initialCont)[a];
leaves[a] = (*node);
}
else
{
const size_t mean = (a + b) / 2;
{
Node* left;
ConstructTree(a, mean, &left);
(*node)->left = left;
(*node)->left->parent = (*node);
}
{
Node* right;
ConstructTree(mean + 1, b, &right);
(*node)->right = right;
(*node)->right->parent = (*node);
}
UpdateNodeValue(*node);
}
}
else
{
(*node) = nullptr;
}
}
void DestructDownwards(Node** node)
{
if ((*node) != nullptr)
{
DestructDownwards(&((*node)->left));
DestructDownwards(&((*node)->right));
delete (*node);
(*node) = nullptr;
}
}
void UpdateNodeValue(Node* node)
{
if (node != nullptr)
{
if ((node->left != nullptr) && (node->right != nullptr))
{
node->val = functor(node->left->val, node->right->val);
}
else
{
if ((node->left != nullptr) && (node->right == nullptr))
{
node->val = node->left->val;
}
else
{
if ((node->left == nullptr) && (node->right != nullptr))
{
node->val = node->right->val;
}
}
}
}
}
void UpdateUpwards(Node* node)
{
if (node != nullptr)
{
UpdateNodeValue(node);
UpdateUpwards(node->parent);
}
}
T GetRange(Node* node, size_t a, size_t b)
{
if (node->b < b)
{
T* ptrMyVal = nullptr;
if (node->parent->right == node)
{
if ((node->a >= a) && (node->b <= b))
{
ptrMyVal = &(node->val);
}
}
if (ptrMyVal != nullptr)
{
return functor(*ptrMyVal, GetRange(node->parent, a, b));
}
else
{
if (node->parent->b > b)
{
if ((node->a >= a) && (node->b <= b))
{
ptrMyVal = &(node->val);
}
}
if (ptrMyVal != nullptr)
{
return functor(*ptrMyVal, GetRange(node->parent, a, b));
}
else
{
return GetRange(node->parent, a, b);
}
}
}
else
{
if (node->b == b)
{
if (node->a >= a)
{
return node->val;
}
else
{
return GetRange(node->right, a, b);
}
}
else
{
return GetRange(node->left, a, b);
}
}
}
private:
TFunc functor;
private:
const std::vector<T>* initialCont;
private:
Node* root;
std::vector<Node*> leaves;
};
#include <fstream>
#include <vector>
using namespace std;
ifstream fin("arbint.in");
ofstream fout("arbint.out");
int main()
{
int n, m;
vector<int> V;
fin >> n >> m;
for (int i = 0; i < n; ++i)
{
int x;
fin >> x;
V.push_back(x);
}
IntervalTree<int, int(*)(int, int)>* it = new IntervalTree<int, int(*)(int, int)>(V, [](int a, int b) { return (a > b) ? a : b; });
for (int i = 0; i < m; ++i)
{
int c, a, b;
fin >> c >> a >> b;
if (c == 0)
{
int* res;
it->GetRange(a - 1, b - 1, &res);
fout << (*res) << '\n';
delete res;
}
else
{
it->UpdateValue(a - 1, b);
}
}
delete it;
fin.close();
fout.close();
return 0;
}