const int MAXN=5e4+5,MAXS=MAXN*40,Inf=0x7fffffff;
template <typename T>
struct Treap{
int pool[MAXS],top,tot;
int root[MAXS],ch[MAXS][2],r[MAXS],sz[MAXS],cnt[MAXS];
T val[MAXS];
int new_node(T v){
int id=top?pool[top--]:++tot;
val[id]=v;r[id]=rand();sz[id]=cnt[id]=1;ch[id][0]=ch[id][1]=0;
return id;
}
void push_up(int id){sz[id]=sz[ch[id][0]]+sz[ch[id][1]]+cnt[id];}
void Rotate(int &id,int dir){
int t=ch[id][dir^1];
ch[id][dir^1]=ch[t][dir];ch[t][dir]=id;id=t;
push_up(ch[id][dir]);push_up(id);
}
void Insert(int &id,T v){
if(!id)
return id=new_node(v),void();
if(v==val[id])
cnt[id]++;
else{
int dir=v<val[id]?0:1;
Insert(ch[id][dir],v);
if(r[id]<r[ch[id][dir]])
Rotate(id,dir^1);
}
push_up(id);
}
void Erase(int &id,T v){
if(!id)
return;
if(v==val[id]){
if(cnt[id]>1)
return cnt[id]--,push_up(id);
else if(!ch[id][0])
pool[++top]=id,id=ch[id][1];
else if(!ch[id][1])
pool[++top]=id,id=ch[id][0];
else{
int d=r[ch[id][0]]>r[ch[id][1]]?1:0;
Rotate(id,d);Erase(ch[id][d],v);push_up(id);
}
}
else{
if(v<val[id])
Erase(ch[id][0],v);
else
Erase(ch[id][1],v);
push_up(id);
}
}
int Rank(int id,T v){//有多少个数严格小于v
if(!id)
return 0;
if(v==val[id])
return sz[ch[id][0]];
else if(v<val[id])
return Rank(ch[id][0],v);
else
return sz[ch[id][0]]+cnt[id]+Rank(ch[id][1],v);
}
T Kth(int id,int rk){
if(!id)
return -1;//第rk小的节点不存在
if(rk>sz[ch[id][0]]+cnt[id])
return Kth(ch[id][1],rk-sz[ch[id][0]]-cnt[id]);
else if(rk>sz[ch[id][0]])
return val[id];
else
return Kth(ch[id][0],rk);
}
T Pre(int id,T v){
int pos=id,ans=-Inf;
while(pos){
if(val[pos]<v){
ans=ans<val[pos]?val[pos]:ans;
pos=ch[pos][1];
}
else
pos=ch[pos][0];
}
return ans;
}
T Suf(int id,T v){
int pos=id,ans=Inf;
while(pos){
if(v<val[pos]){
ans=ans<val[pos]?ans:val[pos];
pos=ch[pos][0];
}
else
pos=ch[pos][1];
}
return ans;
}
void insert(int root_id,T v){Insert(root[root_id],v);}
void erase(int root_id,T v){Erase(root[root_id],v);}
int rank(int root_id,T v){return Rank(root[root_id],v);}
T kth(int root_id,int rk){return Kth(root[root_id],rk);}
T pre(int root_id,T v){return Pre(root[root_id],v);}
T suf(int root_id,T v){return Suf(root[root_id],v);}
bool empty(int root_id){return sz[root_id]==0;}
};
const int MAXV=1e8;
struct Tree{
Treap<int> S;
int root,a[MAXN],pool[MAXS],top,tot,lson[MAXS],rson[MAXS];
int New(){
int k=top?pool[top--]:++tot;
lson[k]=rson[k]=0;
return k;
}
void Del(int &k){
pool[++top]=k;
k=0;
}
void Insert(int &k,int lef,int rig,int v,int pos){
if(!k)k=New();
S.insert(k,pos);
if(lef==rig)
return;
int mid=lef+rig>>1;
if(v<=mid)
Insert(lson[k],lef,mid,v,pos);
else
Insert(rson[k],mid+1,rig,v,pos);
}
void insert(int pos,int v){Insert(root,0,MAXV,v,pos);}
void build(int n){
_rep(i,1,n)
insert(i,a[i]);
}
void Erase(int &k,int lef,int rig,int v,int pos){
S.erase(k,pos);
if(lef==rig){
if(S.empty(k))
Del(k);
return;
}
int mid=lef+rig>>1;
if(v<=mid)
Erase(lson[k],lef,mid,v,pos);
else
Erase(rson[k],mid+1,rig,v,pos);
if(S.empty(k))
Del(k);
}
void erase(int pos,int v){Erase(root,0,MAXV,v,pos);}
int Rank(int k,int lef,int rig,int v,int pos1,int pos2){
if(!k)
return 0;
if(rig<=v)
return S.rank(k,pos2)-S.rank(k,pos1);
int mid=lef+rig>>1;
if(mid>=v)
return Rank(lson[k],lef,mid,v,pos1,pos2);
else
return Rank(lson[k],lef,mid,v,pos1,pos2)+Rank(rson[k],mid+1,rig,v,pos1,pos2);
}
int rank(int L,int R,int v){return Rank(root,0,MAXV,v-1,L,R+1)+1;}
int kth(int L,int R,int rk){
if(rk==0)
return -Inf;
else if(rk>R-L+1)
return Inf;
int k=root,lef=0,rig=MAXV,mid,trk;
R++;rk--;
while(lef<rig){
trk=S.rank(lson[k],R)-S.rank(lson[k],L);
mid=lef+rig>>1;
if(rk>=trk)
rk-=trk,k=rson[k],lef=mid+1;
else
k=lson[k],rig=mid;
}
return lef;
}
void update(int pos,int v){
erase(pos,a[pos]);
insert(pos,v);
a[pos]=v;
}
int count(int L,int R,int v){
int k=root,lef=0,rig=MAXV,mid;
while(lef!=rig){
if(!k)
return 0;
mid=lef+rig>>1;
if(v<=mid){
k=lson[k];
rig=mid;
}
else{
k=rson[k];
lef=mid+1;
}
}
return S.rank(k,R+1)-S.rank(k,L);
}
int pre(int L,int R,int v){return kth(L,R,rank(L,R,v)-1);}
int suf(int L,int R,int v){return kth(L,R,rank(L,R,v)+count(L,R,v));}
}tree;
int main()
{
int n=read_int(),m=read_int(),opt,l,r,pos,k,ans;
_rep(i,1,n)
tree.a[i]=read_int();
tree.build(n);
while(m--){
opt=read_int();
if(opt==3){
pos=read_int(),k=read_int();
tree.update(pos,k);
}
else{
l=read_int(),r=read_int(),k=read_int();
switch(opt){
case 1:
ans=tree.rank(l,r,k);
break;
case 2:
ans=tree.kth(l,r,k);
break;
case 4:
ans=tree.pre(l,r,k);
break;
case 5:
ans=tree.suf(l,r,k);
break;
}
enter(ans);
}
}
return 0;
}