#include <cstdio>
#include <algorithm>
const int DIM = 131072;
using namespace std;
class nrx_input_reader {
private:
FILE *input_file;
static const int SIZE = 1 << 19;
char *buffer; int cursor, sign;
long long fractional_part;
void advance() {
if( ++cursor == SIZE ) {
cursor = 0;
fread( buffer, SIZE, 1, input_file );
}
return;
}
public:
nrx_input_reader( const char *file_name, const char *file_type ) {
input_file = fopen( file_name, file_type ); cursor = 0;
buffer = new char[SIZE]; fread( buffer, SIZE, 1, input_file );
}
~nrx_input_reader() {
fclose( input_file );
delete buffer;
}
template <class Type>
nrx_input_reader &operator >>( Type &value ) {
value = 0; sign = 1; fractional_part = 10;
while( buffer[cursor] < '0' || buffer[cursor] > '9' ) {
if( buffer[cursor] == '-' )
sign = -1;
advance();
}
while( buffer[cursor] >= '0' && buffer[cursor] <= '9' ) {
value = value * 10 + ( buffer[cursor] - '0' ) * sign;
advance();
}
if( buffer[cursor] == '.' ) {
advance();
while( buffer[cursor] >= '0' && buffer[cursor] <= '9' ) {
value += ( buffer[cursor] - '0' ) * 1.0 * sign / fractional_part;
advance();
}
}
return *this;
}
nrx_input_reader &operator >>( char *string_pos ) {
while( buffer[cursor] == ' ' || buffer[cursor] == '\n' )
advance();
while( buffer[cursor] != ' ' && buffer[cursor] != '\n' ) {
*string_pos = buffer[cursor]; string_pos ++;
advance();
}
return *this;
}
};
template <typename Type>
Type nrx_max( Type A, Type B ) {
return A > B ? A : B;
}
template <typename Type>
Type nrx_min( Type A, Type B ) {
return A < B ? A : B;
}
template <class Type>
struct nrx_segment_tree {
private:
static const int INF = 0x3f3f3f3f; // TREBUIE MODIFICAT
Type *left_index, *right_index;
struct tree_node {
Type minim, maxim, lazy, sum, type;
tree_node *left_son, *right_son;
tree_node() {
minim = +INF; maxim = -INF;
lazy = sum = type = NULL;
left_son = right_son = NULL;
}
} *root = new tree_node;
void reset_tree( tree_node *node ) {
if( node -> left_son != NULL )
reset_tree( node -> left_son );
if( node -> right_son != NULL )
reset_tree( node -> right_son );
if( node != root )
delete node;
else {
node -> left_son = node -> right_son = NULL; node -> lazy = node -> type = NULL;
node -> minim = +INF; node -> maxim = -INF; node -> sum = NULL;
}
return;
}
void update_lazy( tree_node *node, int left, int right ) {
switch( node -> type ) {
case 1: { // ADD( left, right, lazy )
node -> minim += node -> lazy;
node -> maxim += node -> lazy;
node -> sum += node -> lazy * ( right - left + 1 );
break;
}
case 2: { // MUL( left, right, lazy )
node -> minim *= node -> lazy;
node -> maxim *= node -> lazy;
node -> sum *= node -> lazy;
break;
}
case 3: { // DIV( left, right, lazy )
node -> minim /= node -> lazy;
node -> maxim /= node -> lazy;
node -> sum /= node -> lazy;
break;
}
case 4: { // SET( left, right, lazy )
node -> minim = node -> lazy;
node -> maxim = node -> lazy;
node -> sum = node -> lazy * ( right - left + 1 );
break;
}
}
if( left != right ) {
node -> left_son -> lazy = node -> lazy; node -> left_son -> type = node -> type;
node -> right_son -> lazy = node -> lazy; node -> right_son -> type = node -> type;
}
node -> lazy = node -> type = 0;
return;
}
void update_node( tree_node *node, int left, int right ) {
int middle = left + ( right - left ) / 2;
if( node -> left_son -> lazy != 0 )
update_lazy( node -> left_son, left, middle );
if( node -> right_son -> lazy != 0 )
update_lazy( node -> right_son, middle + 1, right );
node -> minim = nrx_min( node -> left_son -> minim, node -> right_son -> minim );
node -> maxim = nrx_max( node -> left_son -> maxim, node -> right_son -> maxim );
node -> sum = node -> left_son -> sum + node -> right_son -> sum;
return;
}
void build_tree( tree_node *node, int left, int right ) {
if( left > right ) return;
if( left == right ) {
node -> minim = *( left_index + left - 1 );
node -> maxim = *( left_index + left - 1 );
node -> sum = *( left_index + left - 1 );
return;
}
node -> left_son = new tree_node;
node -> right_son = new tree_node;
int middle = left + ( right - left ) / 2;
build_tree( node -> left_son, left, middle );
build_tree( node -> right_son, middle + 1, right );
update_node( node, left, right );
return;
}
void add_value( tree_node *node, int left, int right, int start, int finish, Type value ) {
if( node -> lazy != 0 )
update_lazy( node, left, right );
if( left > right || left > finish || start > right )
return;
if( start <= left && right <= finish ) {
node -> minim += value;
node -> maxim += value;
node -> sum += value * ( right - left + 1 );
if( left != right ) {
node -> left_son -> lazy = node -> left_son -> type != node -> type ? value : node -> left_son -> lazy + value;
node -> right_son -> lazy = node -> right_son -> type != node -> type ? value : node -> right_son -> lazy + value;
node -> left_son -> type = node -> right_son -> type = 1;
}
return;
}
int middle = left + ( right - left ) / 2;
add_value( node -> left_son, left, middle, start, finish, value );
add_value( node -> right_son, middle + 1, right, start, finish, value );
update_node( node, left, right );
return;
}
void mul_value( tree_node *node, int left, int right, int start, int finish, Type value ) {
if( node -> lazy != 0 )
update_lazy( node, left, right );
if( left > right || left > finish || start > right )
return;
if( start <= left && right <= finish ) {
node -> minim *= value;
node -> maxim *= value;
node -> sum *= value;
if( left != right ) {
node -> left_son -> lazy = node -> left_son -> type != node -> type ? value : node -> left_son -> lazy * value;
node -> right_son -> lazy = node -> right_son -> type != node -> type ? value : node -> right_son -> lazy * value;
node -> left_son -> type = node -> right_son -> type = 2;
}
return;
}
int middle = left + ( right - left ) / 2;
mul_value( node -> left_son, left, middle, start, finish, value );
mul_value( node -> right_son, middle + 1, right, start, finish, value );
update_node( node, left, right );
return;
}
void div_value( tree_node *node, int left, int right, int start, int finish, Type value ) {
if( node -> lazy != 0 )
update_lazy( node, left, right );
if( left > right || left > finish || start > right )
return;
if( start <= left && right <= finish ) {
node -> minim *= value;
node -> maxim *= value;
node -> sum *= value;
if( left != right ) {
node -> left_son -> lazy = node -> left_son -> type != node -> type ? value : node -> left_son -> lazy * value;
node -> right_son -> lazy = node -> right_son -> type != node -> type ? value : node -> right_son -> lazy * value;
node -> left_son -> type = node -> right_son -> type = 3;
}
return;
}
int middle = left + ( right - left ) / 2;
div_value( node -> left_son, left, middle, start, finish, value );
div_value( node -> right_son, middle + 1, right, start, finish, value );
update_node( node, left, right );
return;
}
void set_value( tree_node *node, int left, int right, int start, int finish, Type value ) {
if( node -> lazy != 0 )
update_lazy( node, left, right );
if( left > right || left > finish || start > right )
return;
if( start <= left && right <= finish ) {
node -> minim = value;
node -> maxim = value;
node -> sum = value * ( right - left + 1 );
if( left != right ) {
node -> left_son -> lazy = node -> right_son -> lazy = value;
node -> left_son -> type = node -> right_son -> type = 4;
}
return;
}
int middle = left + ( right - left ) / 2;
set_value( node -> left_son, left, middle, start, finish, value );
set_value( node -> right_son, middle + 1, right, start, finish, value );
update_node( node, left, right );
return;
}
Type get_min( tree_node *node, int left, int right, int start, int finish ) {
Type value1, value2, value3; value3 = INF;
if( node -> lazy != 0 )
update_lazy( node, left, right );
if( left > right || left > finish || start > right )
return value3;
if( start <= left && right <= finish )
return node -> minim;
int middle = left + ( right - left ) / 2;
value1 = get_min( node -> left_son, left, middle, start, finish );
value2 = get_min( node -> right_son, middle + 1, right, start, finish );
value3 = nrx_min( value1, value2 );
return value3;
}
Type get_max( tree_node *node, int left, int right, int start, int finish ) {
Type value1, value2, value3; value3 = -INF;
if( node -> lazy != 0 )
update_lazy( node, left, right );
if( left > right || left > finish || start > right )
return value3;
if( start <= left && right <= finish )
return node -> maxim;
int middle = left + ( right - left ) / 2;
value1 = get_max( node -> left_son, left, middle, start, finish );
value2 = get_max( node -> right_son, middle + 1, right, start, finish );
value3 = nrx_max( value1, value2 );
return value3;
}
Type get_sum( tree_node *node, int left, int right, int start, int finish ) {
Type value1, value2, value3; value3 = 0;
if( node -> lazy != 0 )
update_lazy( node, left, right );
if( left > right || left > finish || start > right )
return value3;
if( start <= left && right <= finish )
return node -> sum;
int middle = left + ( right - left ) / 2;
value1 = get_sum( node -> left_son, left, middle, start, finish );
value2 = get_sum( node -> right_son, middle + 1, right, start, finish );
value3 = value1 + value2;
return value3;
}
public:
void build_tree( Type *start_pos, Type *finish_pos ) {
reset_tree( root ); left_index = start_pos; right_index = finish_pos;
build_tree( root, 1, right_index - left_index );
return;
}
void add_value( Type *start_pos, Type *finish_pos, Type value ) {
add_value( root, 1, right_index - left_index, start_pos - left_index + 1, finish_pos - left_index, value );
return;
}
void mul_value( Type *start_pos, Type *finish_pos, Type value ) {
mul_value( root, 1, right_index - left_index, start_pos - left_index + 1, finish_pos - left_index, value );
return;
}
void div_value( Type *start_pos, Type *finish_pos, Type value ) {
div_value( root, 1, right_index - left_index, start_pos - left_index + 1, finish_pos - left_index, value );
return;
}
void set_value( Type *start_pos, Type *finish_pos, Type value ) {
set_value( root, 1, right_index - left_index, start_pos - left_index + 1, finish_pos - left_index, value );
return;
}
Type get_min( Type *start_pos, Type *finish_pos ) {
return get_min( root, 1, right_index - left_index, start_pos - left_index + 1, finish_pos - left_index );
}
Type get_max( Type *start_pos, Type *finish_pos ) {
return get_max( root, 1, right_index - left_index, start_pos - left_index + 1, finish_pos - left_index );
}
Type get_sum( Type *start_pos, Type *finish_pos ) {
return get_sum( root, 1, right_index - left_index, start_pos - left_index + 1, finish_pos - left_index );
}
}; nrx_segment_tree <int> my_segment_tree;
int V[DIM], N, M, K, X, Y;
int main () {
nrx_input_reader input_file( "arbint.in" , "r" );
freopen ("arbint.out","w", stdout);
input_file >> N >> M;
for( int i = 1; i <= N; i ++ )
input_file >> V[i];
my_segment_tree.build_tree( V + 1, V + N + 1 );
for( int i = 1; i <= M; i ++ ) {
input_file >> K >> X >> Y;
switch( K ) {
case 0: {
printf( "%d\n", my_segment_tree.get_max( V + X, V + Y + 1 ) );
break;
}
case 1: {
my_segment_tree.set_value( V + X, V + X + 1, Y );
break;
}
}
}
return 0;
}