#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<stack>
#include<vector>
#define Tp Treap*
#define DTp pair<Tp,Tp>
#define ft first
#define sc second
#define MAXN 50000+10
#define INF 2147483647
using namespace std;
struct SBT{
struct Treap{
Tp l;Tp r;
int key,size,fix;
};
Tp root;
int Size(Tp A){
return (A?A->size:0);
}
void upd(Tp A){
A->size=Size(A->l)+Size(A->r)+1;
}
void Print(Tp A,int k){
if(!A)return;
Print(A->l,k+1);
printf("%d,",A->key);
Print(A->r,k+1);
if(!k)printf("\n");
}
Tp new_treap(int v){
Tp ret;ret=new Treap();
ret->l=ret->r=NULL;
ret->key=v,ret->size=1,ret->fix=rand();
return ret;
}
Tp Build(int a[],int L,int R){
vector<int> b;
stack<Tp> s;
Tp lst;
for(int i=L;i<=R;i++)b.push_back(a[i]);
sort(b.begin(),b.end());
for(int i=0;i<b.size();i++){
Tp x=new_treap(b[i]);
lst=NULL;
while(!s.empty()&&s.top()->fix>x->fix){
upd(s.top());
lst=s.top();
s.pop();
}
if(!s.empty()) s.top()->r=x;
x->l=lst;
s.push(x);
}
while(!s.empty()){
upd(s.top());
lst=s.top();
s.pop();
}
return lst;
}
Tp Merge(Tp A,Tp B){
if(!A)return B;
if(!B)return A;
if(A->fix<B->fix){
A->r=Merge(A->r,B);
upd(A);
return A;
}
else{
B->l=Merge(A,B->l);
upd(B);
return B;
}
}
DTp Split(Tp A,int k){
if(!A)return DTp(NULL,NULL);
DTp y;
if(Size(A->l)>=k){
y=Split(A->l,k);
A->l=y.sc;
upd(A);
y.sc=A;
}
else{
y=Split(A->r,k-Size(A->l)-1);
A->r=y.ft;
upd(A);
y.ft=A;
}
return y;
}
int GetKth(Tp A,int v){
if(!A)return 0;
return (v<=A->key?GetKth(A->l,v):GetKth(A->r,v)+Size(A->l)+1);
}
int Pre(int v){
int k=GetKth(root,v);
if(!k)return -INF; //!!!
DTp x=Split(root,k-1);
DTp y=Split(x.sc,1);
int ans=(y.ft?y.ft->key:-INF);
root=Merge(x.ft,Merge(y.ft,y.sc));
return ans;
}
int Nxt(int v){
int k=GetKth(root,v+1);
DTp x=Split(root,k);
DTp y=Split(x.sc,1);
int ans=(y.ft?y.ft->key:INF);
root=Merge(x.ft,Merge(y.ft,y.sc));
return ans;
}
void Delete(int v){
int k=GetKth(root,v);
DTp x=Split(root,k);
DTp y=Split(x.sc,1);
root=Merge(x.ft,y.sc);
}
void Insert(int v){
int k=GetKth(root,v);
DTp x=Split(root,k);
Tp t=new_treap(v);
root=Merge(x.ft,Merge(t,x.sc));
}
}dat[MAXN<<2];
int a[MAXN];
int n,m;
void build(int k,int L,int R){
dat[k].root=dat[k].Build(a,L,R-1);
if(L+1==R)return;
build(k<<1,L,(L+R)>>1);
build(k<<1|1,(L+R)>>1,R);
}
int rk(int a,int b,int k,int L,int R,int x){// ret=ans-1
int mid=(L+R)>>1;
if(a<=L&&R<=b)return dat[k].GetKth(dat[k].root,x);
if(b<=mid)return rk(a,b,k<<1,L,mid,x);
if(a>=mid)return rk(a,b,k<<1|1,mid,R,x);
return rk(a,b,k<<1,L,mid,x)+rk(a,b,k<<1|1,mid,R,x);
}
int getx(int a,int b,int k){
int L=0,R=100000000;
while(R-L>1){
int mid=(L+R)>>1;
int k1=rk(a,b+1,1,1,n+1,mid)+1;
int k2=rk(a,b+1,1,1,n+1,mid+1);
if(k1<=k&&k<=k2)return mid;
if(k2<k){
L=mid;
}
else if(k1>k){
R=mid;
}
}
int k1=rk(a,b+1,1,1,n+1,L);k1++;
int k2=rk(a,b+1,1,1,n+1,L+1);
if(k1<=k&&k<=k2)return L;
else return R;
}
int pre(int a,int b,int k,int L,int R,int x){
int mid=(L+R)>>1;
if(a<=L&&R<=b)return dat[k].Pre(x);
if(b<=mid)return pre(a,b,k<<1,L,mid,x);
if(a>=mid)return pre(a,b,k<<1|1,mid,R,x);
return max(pre(a,b,k<<1,L,mid,x),pre(a,b,k<<1|1,mid,R,x));
}
int nxt(int a,int b,int k,int L,int R,int x){
int mid=(L+R)>>1;
if(a<=L&&R<=b)return dat[k].Nxt(x);
if(b<=mid)return nxt(a,b,k<<1,L,mid,x);
if(a>=mid)return nxt(a,b,k<<1|1,mid,R,x);
return min(nxt(a,b,k<<1,L,mid,x),nxt(a,b,k<<1|1,mid,R,x));
}
void update(int a,int k,int L,int R,int x,int y){
dat[k].Delete(x);
dat[k].Insert(y);
if(L+1==R)return;
int mid=(L+R)>>1;
if(a<mid)update(a,k<<1,L,mid,x,y);
else update(a,k<<1|1,mid,R,x,y);
}
void init(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
build(1,1,n+1);
}
void AskRk(){
int L,R,x;
scanf("%d%d%d",&L,&R,&x);
printf("%d\n",rk(L,R+1,1,1,n+1,x)+1);
}
void AskNum(){
int L,R,k;
scanf("%d%d%d",&L,&R,&k);
printf("%d\n",getx(L,R,k));
}
void AskUpd(){
int pos,x;
scanf("%d%d",&pos,&x);
update(pos,1,1,n+1,a[pos],x);
a[pos]=x;
}
void AskPre(){
int L,R,x;
scanf("%d%d%d",&L,&R,&x);
int ans=pre(L,R+1,1,1,n+1,x);
printf("%d\n",(ans<x?ans:-INF));
}
void AskNxt(){
int L,R,x;
scanf("%d%d%d",&L,&R,&x);
int ans=nxt(L,R+1,1,1,n+1,x);
printf("%d\n",(ans>x?ans:INF));
}
void solve(){
int opt;
while(m--){
scanf("%d",&opt);
switch(opt){
case 1:AskRk();break;
case 2:AskNum();break;
case 3:AskUpd();break;
case 4:AskPre();break;
case 5:AskNxt();
}
}
}
int main()
{
// freopen("data.in","r",stdin);
// freopen("my.out","w",stdout);
init();
solve();
return 0;
}