#include <fstream>
using namespace std;
ifstream f("arbint.in");
ofstream g("arbint.out");
int arbore[400001];
int v[100001];
void constr(int indice, int st, int dr) //st si dr sunt capetele intervalului asociat nodului indice
{
if(st == dr) //daca am ajuns intr-o frunza
{
arbore[indice] = v[st];
}
else { //daca suntem pe un interval
constr(indice * 2, st, (st + dr) / 2); //construim subarborele stang
constr(indice * 2 + 1, (st + dr) / 2 + 1, dr); //construim subarborele drept
arbore[indice] = max(arbore[indice * 2], arbore[indice * 2 + 1]);
//punem in nodul nostru maximul dintre nodurile radacina ale celor doi subarbori
}
}
void schimb(int indice_curent, int st, int dr, int indice, int val)
{
//cu indice_curent ma plimb prin arbore, indice e cel din vector pe care trebuie sa-l modific
if(st == dr)
{
//am ajuns in nodul frunza pe care il cautam
v[indice] = val;
arbore[indice_curent] = val;
}
else {
//cautam indicele in arbore
if(st <= indice && indice <= (st + dr) / 2) //daca e in intervalul asociat subarborelui stang
schimb(indice_curent * 2, st, (st + dr) / 2, indice, val);
else schimb(indice_curent * 2 + 1, (st + dr) / 2 + 1, dr, indice, val); //e in intervalul asociat subarborelui drept
//reactualizam indicele nodului curent
arbore[indice_curent] = max(arbore[indice_curent * 2], arbore[indice_curent * 2 + 1]);
}
}
int maxim(int indice, int st, int dr, int limInf, int limSup) //vr maximul pe intervalul [limInf, limSup]
{
//daca am iesit din intervalul cautat
if(limSup < st || limInf > dr)
return -1; //numar miiiic
if(limInf <= st && dr <= limSup) //daca acoperim complet intervalul curent
return arbore[indice];
//daca nu calculam maximele pe subarbori
return max(maxim(indice * 2, st, (st + dr) / 2, limInf, limSup), maxim(indice * 2 + 1, (st + dr) / 2 + 1, dr, limInf, limSup));
}
int main()
{
int n, m;
f >> n >> m;
for(int i = 1; i <= n; i++)
{
int element;
f >> element;
v[i] = element;
}
constr(1, 1, n);
for(int i = 1; i <= m; i++)
{
int optiune, a, b;
f >> optiune >> a >> b;
switch(optiune)
{
case 0:
{
g << maxim(1, 1, n, a, b) << endl;
break;
}
case 1:
{
schimb(1, 1, n, a, b);
break;
}
}
}
f.close();
g.close();
return 0;
}