/* 单点更新,区间查询最值 */
/* 注意线段树的大小要比需要使用线段树的数据的个数 大3到4倍 */
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std ;
#define maxn 4000001
struct node {
int le , ri ;
int num ;
};
node tree[maxn*4] ;
int a[maxn] ;
int n , m ;
char ch ;
int x , y ;
void build(int root , int l , int r){
if(l == r){
tree[root].le = tree[root].ri = l ;
tree[root].num = a[l] ;
return;
}
tree[root].le = l ;
tree[root].ri = r ;
int mid = (l + r) /2 ;
build(root*2 , l , mid) ;
build(root*2+1 , mid + 1 , r) ;
tree[root].num = max(tree[root*2].num , tree[root*2+1].num) ;
}
// 单点更新 (二叉查询)
void update(int root , int pos , int value ){
if(tree[root].le == pos && tree[root].ri == pos){
tree[root].num = value ;
return;
}
int mid = (tree[root].le + tree[root].ri)/2 ;
if(pos <= mid){//(二叉查询)
update(root*2 , pos , value) ;
} else {
update(root*2+1 , pos , value) ;
}
tree[root].num = max(tree[root*2].num , tree[root*2+1].num) ;
}
//查询区间【start,end】中的最大值
int query(int root , int start , int ends){
if(tree[root].le == start && tree[root].ri == ends){
return tree[root].num ;
}
int mid = (tree[root].le + tree[root].ri)/2 ;
//[start,mid] (mid , ends] .
if( mid < start ){
return query(root*2+1 , start , ends) ;
} else if(ends <= mid ){
return query(root*2 , start , ends) ;
} else if( start <= mid && mid < ends){
return max(query(root*2 , start , mid) , query(root*2+1 , mid+1 , ends) ) ;
}
}
int main(){
while(~scanf("%d%d" , &n , &m)){
for(int i=1 ; i<=n ; i++){
scanf("%d" , &a[i]) ;
}
build(1 , 1 , n ) ;
for(int i=1 ; i<=m ; i++){
scanf(" %c" , &ch) ;
scanf("%d%d" , &x , &y) ;
if(ch == 'Q'){
printf("%d
" , query(1 ,x , y )) ;
}
if(ch == 'U'){
update(1 , x , y ) ;
}
cout<<1<<endl ;
}
}
return 0 ;
}