#include<bits/stdc++.h>
using namespace std;
#define lc t[x].ch[0]
#define rc t[x].ch[1]
const int N=3e5+5;
struct node{int fa,ch[2],sum,val,lazy;}t[N];
bool isRoot(int x){
int grand=t[x].fa;
return t[grand].ch[0]!=x&&t[grand].ch[1]!=x;
}
void push_up(int x){
t[x].sum=t[x].val^t[lc].val^t[rc].val;
}
void Reverse(int x){
if(!x) return ;
swap(lc,rc);
t[x].lazy^=1;
}
void push_down(int x){
if(t[x].lazy){
Reverse(lc);
Reverse(rc);
t[x].lazy;
}
}
void push(int x){
if(!isRoot(x)) push(t[x].fa);
push_down(x);
}
void rotate(int x){
int y=t[x].fa;
int z=t[y].fa;
int k=t[y].ch[1]==x;
if(!isRoot(y)) t[z].ch[t[z].ch[1]==y]=x;
t[x].fa=z;
t[y].ch[k]=t[x].ch[k^1];
if(t[x].ch[k^1])t[t[x].ch[k^1]].fa=y;
t[y].fa=x;
t[x].ch[k^1]=y;
push_up(x);
}
void splay(int x){
int y,z;
push(x);
while(!isRoot(x)){
y=t[x].fa,z=t[y].fa;
if(!isRoot(y)) (t[z].ch[0]==y)^(t[y].ch[0]==x)?rotate(x):rotate(y);
rotate(x);
}
push_up(x);
}
void access(int x){
for(int child=0;x;child=x,x=t[x].fa){
splay(x);
rc=child;
push_up(x);
}
}
void make_root(int x){
access(x);splay(x);Reverse(x);
}
void split(int x,int y){
make_root(x);
access(y);
splay(y);
}
void link(int x,int y){
make_root(x);t[x].fa=y;
}
void cut(int x,int y){
split(x,y);
if(t[y].ch[0]!=x||rc) return ;
t[x].fa=t[y].ch[0]=0;
push_up(x);
}
int find_root(int x){
access(x);splay(x);
while(rc) push_down(x),x=lc;
return x;
}
int main(){
int n,m;scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){scanf("%d",&t[i].val);t[i].sum=t[i].val;}
while(m--){
int opt,a,b;scanf("%d%d%d",&opt,&a,&b);
switch(opt){
case 0:split(a,b);printf("%d\n",t[b].sum);break;
case 1:if(find_root(a)!=find_root(b)) link(a,b);break;
case 2:cut(a,b);break;
case 3:splay(a);t[a].val=b;break;
}
}
return 0;
}