#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#define ls (node<<1)
#define rs ((node<<1)|1)
#define mid ((l+r)>>1)
using namespace std;
const int maxn=1e5+5;
int n,m,A,OP,S,V,L,R,D,X;
bool K;
int tot,cnt1,cnt2;
int root[maxn],ans[maxn],st[maxn];
vector<int> v[maxn<<2];
struct node{
int NEXT[2],sum;
}tree[maxn<<5];
struct ask{
int s,v,t;
}goods[maxn],t1[maxn],t2[maxn];
struct change{
int lg,rg,tl,tr,x;
}que[maxn];
bool cmp(ask x,ask y){
return x.s<y.s;
}
int update(int node1,int node2,int k){
int res=node2=++tot;
for(int i=17;i>=0;i--){
K=k&(1<<i);
tree[node2].NEXT[K]=++tot;
tree[node2].NEXT[!K]=tree[node1].NEXT[!K];
node1=tree[node1].NEXT[K];
node2=tree[node2].NEXT[K];
tree[node2].sum=tree[node1].sum+1;//ÊÇÏÂÒ»¸öλÖüÓÒ»
}
return res;
}
int query(int node1,int node2,int k){
int res=0;
for(int i=17;i>=0;i--){
K=k&(1<<i);
if(tree[tree[node2].NEXT[!K]].sum-tree[tree[node1].NEXT[!K]].sum>0){
node1=tree[node1].NEXT[!K];
node2=tree[node2].NEXT[!K];
res+=(1<<i);
}
else{
node1=tree[node1].NEXT[K];
node2=tree[node2].NEXT[K];
}
}
return res;
}
void update2(int node,int l,int r,int aim_L,int aim_R,int k){
// cout<<l<<' '<<r<<endl;
if(l>aim_R||r<aim_L)//use || not &&
return ;
if(aim_L<=l&&r<=aim_R){
v[node].push_back(k);
return ;//do not forget
}
update2(ls,l,mid,aim_L,aim_R,k);
update2(rs,mid+1,r,aim_L,aim_R,k);
return ;
}
void calc(int node,int l,int r){
int top=tot=0;
for(int i=l;i<=r;i++){
st[++top]=goods[i].s;
root[top]=update(root[i-1],root[i],goods[i].v);
cout<<root[top]<<endl<<endl;
}
for(int i=0;i<v[node].size();i++){
int k=v[node][i];
cout<<ans[k]<<' ';
int ll=upper_bound(st+1,st+top+1,que[k].lg-1)-st-1;
int rr=upper_bound(st+1,st+top+1,que[k].rg)-st-1;
ans[k]=max(ans[k],query(root[ll],root[rr],que[k].x));
cout<<k<<' '<<ans[k]<<endl;
}
}
void divide(int node,int l,int r,int aim_L,int aim_R){
if(aim_L>aim_R)
return ;
calc(node,aim_L,aim_R);
int tot1=0,tot2=0;
if(l==r)
return ;
for(int i=aim_L;i<=aim_R;i++)
if(goods[i].t<=mid)
t1[++tot1]=goods[i];
else
t2[++tot2]=goods[i];
for(int i=1;i<=tot1;i++)
goods[i+aim_L-1]=t1[i];
for(int i=1;i<=tot2;i++)
goods[i+aim_L+tot1-1]=t2[i];
divide(ls,l,mid,aim_L,aim_L+tot1-1);
divide(rs,mid+1,r,aim_L+tot1,aim_R);
return ;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&A);
root[i]=update(root[i-1],root[i],A);
}
while(m--){
scanf("%d",&OP);
if(OP){
scanf("%d%d%d%d",&L,&R,&X,&D);
que[++cnt1].lg=L;
que[cnt1].rg=R;
que[cnt1].tl=max(1,cnt2-D+1);
que[cnt1].tr=cnt2;
que[cnt1].x=X;
ans[cnt1]=query(root[L-1],root[R],X);
}
else{
scanf("%d%d",&S,&V);
goods[++cnt2].s=S;
goods[cnt2].t=cnt2;
goods[cnt2].v=V;
}
}
for(int i=1;i<=cnt1;i++)
update2(1,1,cnt2,que[i].tl,que[i].tr,i);
sort(goods+1,goods+cnt2+1,cmp);
divide(1,1,cnt2,1,cnt2);
for(int i=1;i<=cnt1;i++)
printf("%d\n",ans[i]);
return 0;
}