#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn=2e5;
int N,Q;
int u,v,w,val;
deque<int> p[maxn];
//int read(){
// char ch = getchar();int x = 0;
// for (; ch >='0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
// return x;
//}
int main(){
while(cin>>N>>Q){
for(int i=0;i<=N;i++)p[i].clear();
for(int i=0;i<Q;i++){
scanf("%d%d%d",&u,&v,&w);
//u=read();v=read();w=read();
if(u==1){
scanf("%d",&val);
//val=read();
if(w==1)p[v].push_back(val); //栈底加入元素val
else p[v].push_front(val); //栈顶加入元素val
}
else if(u==2){
if(!p[v].empty()){ //判断是否为空
if(w==1){printf("%d\n",p[v].back());p[v].pop_back();} //删除栈底元素
else {printf("%d\n",p[v].front());p[v].pop_front();} //删除栈顶。。
}
else printf("-1\n");
//if(ff)cout<<"-1\n";
}
else{
scanf("%d",&val);
int l=p[w].size(); //计算元素个数
if(val==0)for(int k=0;k<l;k++)p[v].push_back(p[w][k]);
else for(int k=l-1;k>=0;k--)p[v].push_back(p[w][k]);
//for(int i=0;i<l;i++)p[w].pop_back();
p[w].clear(); //清空
}
}
//for(int i=0;i<N;i++)p[i].clear();
}
return 0;
}