rt
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ls tr[x][0]
#define rs tr[x][1]
int tr[100100][2],fa[100100],ans[100100],val[100100];
bool tag[100100];
int n,m;
int getp(int x){
return x==tr[fa[x]][1];
}
bool root(int x){
if(tr[fa[x]][0]==x||tr[fa[x]][1]==x) return 0;
return 1;
}
void upd(int x){
ans[x]=ans[ls]^ans[rs]^val[x];
}
void reverse(int x){
swap(ls,rs);
tag[x]^=1;
}
void pushdown(int x){
if(tag[x]){
if(ls) reverse(ls);
if(rs) reverse(rs);
tag[x]=0;
}
}
void pushup(int x){
if(!root(x)) pushup(fa[x]);
pushdown(x);
}
void rotate(int x){
int y=fa[x],z=fa[y],w=tr[x][getp(x)^1];
if(!root(y)){
tr[y][getp(x)]=w;
tr[x][getp(x)^1]=y;
tr[z][getp(y)]=x;
}
fa[x]=z;
fa[y]=x;
if(w){
fa[w]=y;
}
upd(x),upd(y);
}
void splay(int x){
int fax=fa[x];
while(!root(x)){
if(!root(fax)){
if(getp(fax)==getp(x)){
rotate(fax);
}else rotate(x);
}
rotate(x);
x=fax,fax=fa[x];
}
upd(x);
}
void access(int x){
int sx=0;
for(;x;sx=x,x=fa[x]){
splay(x);
tr[x][1]=sx;
upd(x);
}
}
void makeroot(int x){
access(x);
splay(x);
reverse(x);
}
int findroot(int x){
access(x);
splay(x);
while(ls){
pushdown(x);
x=ls;
}
return x;
}
void split(int x,int y){
makeroot(x);
access(y);
splay(y);
}
void link(int x,int y){
makeroot(x);
if(findroot(y)!=x){
fa[x]=y;
}
upd(y);
}
void cut(int x,int y){
makeroot(x);
if(findroot(y)==x&&fa[y]==x&&!tr[y][0]){
tr[x][1]=0;
fa[y]=0;
upd(x);
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>val[i];
}
while(m--){
int opt,x,y;
cin>>opt>>x>>y;
if(opt==0){
split(x,y);
cout<<ans[y]<<endl;
}else if(opt==1){
link(x,y);
}else if(opt==2){
cut(x,y);
}else {
splay(x);
val[x]=y;
}
}
return 0;
}