#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=100005;
int n,m;
struct LCT {
int fa[MAXN],val[MAXN],rev[MAXN],ch[MAXN][2],sum[MAXN],tot;
int stk[MAXN],tp;
void up(int x) {
sum[x]=sum[ch[x][0]]^sum[ch[x][1]]^val[x];
}
void push_rev(int x) {
rev[x]^=1;
swap(ch[x][0],ch[x][1]);
}
void down(int x) {
if(rev[x]) {
rev[x]=0;
push_rev(ch[x][0]);
push_rev(ch[x][1]);
}
}
int get(int x) {
return ch[fa[x]][1]==x;
}
bool isroot(int x) {
return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;
}
void rotate(int x) {
int f1=fa[x],f2=fa[f1],id=get(x);
ch[f1][id]=ch[x][id^1]; fa[ch[f1][id]]=f1;
if(!isroot(f1)) ch[f2][get(f1)]=x; fa[x]=f2; //!!!!!
ch[x][id^1]=f1; fa[f1]=x;
up(f1);
}
void splay(int x) {
tp=0;
int y=x;
stk[++tp]=y; //!!!!!
while(!isroot(y)) stk[++tp]=y=fa[y];
while(tp) down(stk[tp--]);
while(!isroot(x)) { //!!!!!
int f1=fa[x],f2=fa[f1];
if(!isroot(f1)) {
if(get(x)==get(f1)) rotate(f1);
else rotate(x);
}
rotate(x);
}
up(x);
}
void access(int x) {
for(int y=0;x;y=x,x=fa[x])
splay(x),ch[x][1]=y,up(x);
}
void makeroot(int x) {
access(x);
splay(x);
push_rev(x);
}
int findroot(int x) {
access(x); splay(x);
while(ch[x][0]) x=ch[x][0];
splay(x);
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;
}
void cut(int x,int y) {
makeroot(x);
if(findroot(y)==x&&fa[y]==x&&!ch[y][0]) { //!!!!!
fa[y]=ch[x][1]=0;
up(x);
}
}
}tr;
int main() {
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&tr.val[i]);
for(int i=1;i<=m;i++) {
int opt,x,y;
scanf("%d%d%d",&opt,&x,&y);
switch(opt) {
case 0: tr.split(x,y); printf("%d\n",tr.sum[y]); break;
case 1: tr.link(x,y); break;
case 2: tr.cut(x,y); break;
case 3: tr.makeroot(x); tr.val[x]=y; tr.up(x); break;
}
}
return 0;
}