#include<iostream>
#define int long long
using namespace std;
const int N=6e5+5;
const int M=2e5+5;
int n,m;
struct node{
int lson;
int rson;
int w;
}tr[4*N];
int cnt=0;
int tot=0;
int rubbish[4*N];
void delnode(int &now){
tr[now].lson=tr[now].rson=tr[now].w=0;
rubbish[++tot]=now;
now=0;
}
int newnode(){
if(tot){
return rubbish[tot--];
}
return ++cnt;
}
int arr[N];
void push_up(int now){
tr[now].w+=tr[tr[now].lson].w+tr[tr[now].rson].w;
}
void build(int &now,int left=1,int right=n){
if(!now){
now=newnode();
}
if(left==right){
tr[now].w=arr[left];
return;
}
int mid=(left+right)>>1;
build(tr[now].lson,left,mid);
build(tr[now].rson,mid+1,right);
push_up(now);
}
void merge(int &tr1,int &tr2,int left=1,int right=n){
if(!tr1||!tr2){
tr1+=tr2;
return;
}
if(left==right){
tr[tr1].w+=tr[tr2].w;
delnode(tr2);
return;
}
int mid=(left+right)>>1;
merge(tr[tr1].lson,tr[tr2].lson,left,mid);
merge(tr[tr1].rson,tr[tr2].rson,mid+1,right);
delnode(tr2);
push_up(tr1);
}
void split(int &tr1,int &tr2,int nowleft,int nowright,int left=1,int right=n){
if(right<nowleft||left>nowright){
return;
}
if(!tr1){
return;
}
if(nowleft<=left&&nowright>=right){
tr2=tr1;
tr1=0;
return;
}
if(!tr2){
tr2=newnode();
}
int mid=(left+right)>>1;
split(tr[tr1].lson,tr[tr2].lson,nowleft,nowright,left,mid);
split(tr[tr1].rson,tr[tr2].rson,nowleft,nowright,mid+1,right);
push_up(tr1);
push_up(tr2);
}
void update(int num,int add,int &now,int left=1,int right=n){
if(num<left||num>right){
return;
}
if(!now){
now=newnode();
}
if(left==right){
tr[now].w+=add;
return;
}
int mid=(left+right)>>1;
update(num,add,tr[now].lson,left,mid);
update(num,add,tr[now].rson,mid+1,right);
push_up(now);
}
int query_sum(int nowleft,int nowright,int now,int left=1,int right=n){
if(nowright<left||nowleft>right){
return 0;
}
if(!now){
return 0;
}
if(nowleft<=left&&nowright>=right){
return tr[now].w;
}
int mid=(left+right)>>1;
return query_sum(nowleft,nowright,tr[now].lson,left,mid)+query_sum(nowleft,nowright,tr[now].rson,mid+1,right);
}
int query_kth(int k,int now,int left=1,int right=n){
if(k<=0){
return -1;
}
if(left==right){
return left;
}
int mid=(left+right)>>1;
if(tr[tr[now].lson].w>=k){
return query_kth(k,tr[now].lson,left,mid);
}
return query_kth(k-tr[tr[now].lson].w,tr[now].rson,mid+1,right);
}
int root[N];
int cnttree=1;
signed main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>arr[i];
}
build(root[1]);
int check,p,t,x,y,k,q,kth;
while(m--){
cin>>check;
if(check==0){
cin>>p>>x>>y;
split(root[p],root[++cnttree],x,y);
}
if(check==1){
cin>>p>>t;
merge(root[p],root[t]);
}
if(check==2){
cin>>p>>x>>q;
update(q,x,root[p]);
}
if(check==3){
cin>>p>>x>>y;
cout<<query_sum(x,y,root[p])<<endl;
}
if(check==4){
cin>>p>>k;
if(query_sum(1,n,root[p])<k){
kth=-1;
}
else{
kth=query_kth(k,root[p]);
}
cout<<kth<<endl;
}
}
return 0;
}