#include<iostream>
#include<cstring>
#include<stdlib.h>
#include<time.h>
using namespace std;
const int N=50010;
int n,m;
int cnt;
struct node{
int l;
int r;
int val;
int key;
int sz;
}fhq[N*40];
struct nd{
int l;
int r;
int root;
}tr[N<<2];
int w[N];
int x,y,z;
void update(int u)
{
fhq[u].sz=fhq[fhq[u].l].sz+1+fhq[fhq[u].r].sz;
}
void split(int now,int val,int &x,int &y)
{
if(!now)
{
x=0,y=0;
return;
}
if(fhq[now].val<=val)
{
x=now;
split(fhq[now].r,val,fhq[now].r,y);
}
else
{
y=now;
split(fhq[now].l,val,x,fhq[now].l);
}
update(now);
}
int merge(int x,int y)
{
if(!x || !y) return x|y;
if(fhq[x].key>fhq[y].key)
{
fhq[x].r=merge(fhq[x].r,y);
update(x);
return x;
}
else
{
fhq[y].l=merge(x,fhq[y].l);
update(y);
return y;
}
}
int newnode(int val)
{
++cnt;
fhq[cnt].val=val;
fhq[cnt].sz=1;
fhq[cnt].key=rand();
return cnt;
}
int getrank(int &root,int val)
{
split(root,val-1,x,y);
int res=fhq[x].sz;
root=merge(x,y);
return res;
}
int kth(int &root,int k)
{
int now=root;
while(now)
{
if(fhq[fhq[now].l].sz+1==k)
break;
else if(fhq[fhq[now].l].sz>=k)
now=fhq[now].l;
else
k-=fhq[fhq[now].l].sz+1,now=fhq[now].r;
}
return fhq[now].val;
}
void insert(int &root,int val)
{
split(root,val-1,x,y);
root=merge(merge(x,newnode(val)),y);
}
void del(int &root,int val)
{
split(root,val,x,y);
split(x,val-1,x,z);
z=merge(fhq[z].l,fhq[z].r);
root=merge(merge(x,z),y);
}
int pre(int &root,int val)
{
split(root,val-1,x,y);
int now=x;
int res=0;
while(fhq[now].r)
now=fhq[now].r;
res=fhq[now].val;
if(!now)
res=-1e9;
root=merge(x,y);
return res;
}
int next(int &root,int val)
{
split(root,val,x,y);
int now=y;
while(fhq[now].l)
now=fhq[now].l;
int res=fhq[now].val;
if(!res)
res=1e9;
root=merge(x,y);
return res;
}
void build(int u,int l,int r)
{
tr[u]={
l,r};
for(int i=l;i<=r;i++)
insert(tr[u].root,w[i]);
if(l==r) return ;
int mid=l+r>>1;
build(u<<1,l,mid),build(u<<1|1,mid+1,r);
}
void mdf(int u,int x,int v)
{
del(tr[u].root,w[x]);
insert(tr[u].root,v);
if(tr[u].l==tr[u].r) return ;
int mid=tr[u].l+tr[u].r>>1;
if(x<=mid)
mdf(u<<1,x,v);
else
mdf(u<<1|1,x,v);
}
int qrrank(int u,int l,int r,int v)
{
if(tr[u].l>=l && tr[u].r<=r)
return getrank(tr[u].root,v);
int mid=tr[u].l+tr[u].r>>1;
int res=0;
if(l<=mid)
res+=qrrank(u<<1,l,r,v);
if(r>mid)
res+=qrrank(u<<1|1,l,r,v);
return res;
}
int qrkth(int l,int r,int k)
{
int L=0,R=1e8;
while(L<R)
{
int mid=L+R+1>>1;
if(qrrank(1,l,r,mid)<k)
L=mid;
else
R=mid-1;
}
return L;
}
int get_pre(int u,int l,int r,int x)
{
if(tr[u].l>=l && tr[u].r<=r)
return pre(tr[u].root,x);
int mid=tr[u].l+tr[u].r>>1;
int res=-1e9;
if(l<=mid)
res=get_pre(u<<1,l,r,x);
if(r>mid)
res=max(res,get_pre(u<<1|1,l,r,x));
return res;
}
int get_next(int u,int l,int r,int x)
{
if(tr[u].l>=l && tr[u].r<=r)
return next(tr[u].root,x);
int mid=tr[u].l+tr[u].r>>1;
int res=1e9;
if(l<=mid)
res=get_next(u<<1,l,r,x);
if(r>mid)
res=min(res,get_next(u<<1|1,l,r,x));
return res;
}
int main()
{
srand(time(NULL));
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>w[i];
build(1,1,n);
while(m--)
{
int op;
cin>>op;
if(op==1)
{
int l,r,x;
cin>>l>>r>>x;
cout<<qrrank(1,l,r,x)+1<<endl;
}
else if(op==2)
{
int l,r,x;
cin>>l>>r>>x;
cout<<qrkth(l,r,x)<<endl;
}
else if(op==3)
{
int x,v;
cin>>x>>v;
mdf(1,x,v);
w[x]=v;
}
else if(op==4)
{
int l,r,x;
cin>>l>>r>>x;
cout<<get_pre(1,l,r,x)<<endl;
}
else if(op==5)
{
int l,r,x;
cin>>l>>r>>x;
cout<<get_next(1,l,r,x)<<endl;
}
}
return 0;
}