#include<stdio.h>
#include<stdlib.h>
typedef struct{
int st;
int dr;
}interval;
typedef struct nod{
interval I;
int maxim;
struct nod * st;
struct nod * dr;
}TNod,*Tarb;
Tarb buildNode(int i, int j)
{
Tarb aux = (Tarb )malloc(1 * sizeof(TNod));
aux->st = NULL;
aux->dr = NULL;
(aux->I).st = i;
(aux->I).dr = j;
aux->maxim = -1;
return aux;
}
Tarb buildTree(int i, int j,int * v)
{
Tarb root = buildNode(i,j);
if(i == j)
{
root->maxim = v[i];
// printf("%d\n",v[i]);
return root;
}
int mij = (i+j)/2;
root->st= buildTree(i,mij,v);
root->dr= buildTree(mij+1,j,v);
root->maxim = ((root->st)->maxim > (root->dr)->maxim) ? (root->st)->maxim : (root->dr)->maxim;
// printf("%d\n",root->maxim);
return root;
}
int Imax(Tarb root,int a,int b)
{
if(a <= (root->I).st && (root->I).dr <= b)
return root->maxim;
int mij = ((root->I).st + (root->I).dr)/2;
int max1 = -1;
int max2 = -1;
if(a <= mij)
max1= Imax(root->st,a,b);
if( b > mij)
max2 = Imax(root->dr,a,b);
return (max1 > max2) ? max1:max2;
}
void actualizare(Tarb root,int a, int b)
{
// printf("%d %d %d \n", a, (root->I).st, (root->I).dr);
if( a <= (root->I).st && (root->I).dr <= a)
{
root->maxim = b;
return;
}
int mij = ((root->I).st + (root->I).dr)/2;
if( a <= mij)
actualizare(root->st, a,b);
if( a > mij)
actualizare(root->dr,a,b);
root->maxim = ((root->st)->maxim > (root->dr)->maxim) ? (root->st)->maxim : (root->dr)->maxim;
}
void SDR(Tarb root)
{
if(root == NULL)
return;
SDR(root->st);
SDR(root->dr);
printf("%d\n",root->maxim);
}
int main(void)
{
FILE * fin = fopen("arbint.in","rt");
FILE * fout = fopen("arbint.out","wt");
int n,m,i;
fscanf(fin,"%d%d",&n,&m);
int *v = (int*) calloc(n+1, sizeof(int));
for(i = 1; i <= n ;i++)
fscanf(fin,"%d",v+i);
Tarb root = buildTree(1,n, v);
// SDR(root);
// printf("\n\n");
int op,a,b;
for(i = 0; i < m; i++)
{
fscanf(fin,"%d%d%d",&op,&a,&b);
if(op == 0)
{
int max = Imax(root,a,b);
fprintf(fout,"%d\n",max);
}
else
{
actualizare(root,a,b);
// SDR(root);
// printf("\n\n");
}
}
fclose(fin);
fclose(fout);
free(v);
return 0;
}