#include<bits/stdc++.h>
#define N 200500
using namespace std;
int n,q,opt,x,y;
int son[N][2],fa[N],val[N];
int route[N];bool lazy[N];
#define ls(x) son[x][0]
#define rs(x) son[x][1]
inline void swap(int &x,int &y)
{x^=y^=x^=y;}
inline bool which(int x)
{return son[fa[x]][1]==x;}
inline bool not_root(int x)
{return (ls(fa[x])==x)||(rs(fa[x])==x);}
inline void pushup(int x)
{route[x]=route[ls(x)]^route[rs(x)]^val[x];}
void pushdown(int x)
{
if(!lazy[x]) return;
swap(ls(x),rs(x));
lazy[ls(x)]^=1; lazy[rs(x)]^=1;
lazy[x]=0;
}
void update(int x)
{
if(not_root(x)) update(fa[x]);
pushdown(x);
}
void rotate(int x) //d=0右旋,d=1左旋
{
bool d=which(x);
if(not_root(fa[x])) son[fa[fa[x]]][which(fa[x])]=x;
son[fa[x]][d]=son[x][d^1];
son[x][d^1]=fa[x];
fa[x]=fa[fa[x]]; fa[son[x][d^1]]=x;
pushup(son[x][d^1]); pushup(x);
}
void splay(int x)
{
update(x);
for(int f;f=fa[x],not_root(x);rotate(x))
if(not_root(f)) rotate(which(x)==which(f)?f:x);
}
void access(int x)
{for(int f=0;x;f=x,x=fa[x]) splay(x),son[x][1]=f,pushup(x);}
void makeroot(int x)
{access(x); splay(x); lazy[x]^=1,pushdown(x);}
void split(int x,int y)
{makeroot(x); access(y); splay(y);}
int findroot(int x)
{
access(x); splay(x);
pushdown(x);
while(ls(x)) pushdown(x=ls(x));
return x;
}
void connect(int x,int y)
{
makeroot(x);
if(findroot(y)!=x) fa[x]=y;
}
void cut(int x,int y)
{
makeroot(x);
if(findroot(y)!=x||fa[x]!=y||rs(x)||ls(y)!=x) return;
son[y][which(x)]=0; fa[x]=0; pushup(y);
}
int main()
{
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++) scanf("%d",&val[i]);
while(q--)
{
scanf("%d%d%d",&opt,&x,&y);
if(opt==0) split(x,y),printf("%d\n",route[y]);
if(opt==1) connect(x,y);
if(opt==2) cut(x,y);
if(opt==3) splay(x),val[x]=y;
}
}