#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define N 100009
#define int long long
long long val[N], ch[N][2], fa[N], lazy[N], sum[N];
inline void updata(int x)
{
sum[x] = sum[ch[x][0]] ^ sum[ch[x][1]] ^ val[x];
}
inline void swap(long long& a, long long& b)
{
a ^= b, b ^= a, a ^= b;
}
inline void push(int x)
{
if (x)
swap(ch[x][1], ch[x][0]), lazy[x] ^= 1;
}
inline void pushdown(int x)
{
if (lazy[x])
{
if (ch[x][0])
push(ch[x][0]);
if (ch[x][1])
push(ch[x][1]);
lazy[x] = 0;
}
}
inline bool isRoot(int x)
{
return x != ch[fa[x]][1] && x != ch[fa[x]][0];
}
inline bool get(int x)
{
return x == ch[fa[x]][1];
}
void Updata(int x)
{
if (!isRoot(x))
Updata(fa[x]);
pushdown(x);
}
inline void rorate(int x)
{
int y = fa[x], z = fa[y], f = get(x);
if (!isRoot(y))
ch[z][get(y)] = x;
ch[y][f] = ch[x][!f], fa[ch[x][!f]] = y;
ch[x][!f] = y, fa[y] = x, fa[x] = z;
updata(y), updata(x);
}
inline void splay(int x)
{
int y;
Updata(x);
while (!isRoot(x))
{
y = fa[x];
if (!isRoot(y))
rorate(get(y) == get(x) ? x : y);
rorate(x);
}
updata(x);
}
inline void access(int x)
{
for (int y = 0;x;x = fa[y = x])
splay(x), ch[x][1] = y, updata(x);
}
inline void makeroot(int x)
{
access(x), splay(x), push(x);
}
inline int findroot(int x)
{
access(x);
splay(x);
while (ch[x][0])
pushdown(x), x = ch[x][0];
splay(x);
return x;
}
inline void split(int x, int y)
{
makeroot(x);
access(y), splay(y);
}
inline void link(int x, int y)
{
makeroot(x);
if (findroot(y) != x)
fa[x] = y;
}
inline void cut(int x, int y)
{
makeroot(x);
if (findroot(y) == x && !ch[y][0] && fa[y] == x)
ch[x][0] = fa[y] = 0, updata(x);
}
signed main()
{
int n, m;
scanf("%lld%lld", &n, &m);
for (int i = 1;i <= n;++ i)
scanf("%lld", &val[i]);
int opt, x, y;
while (m --)
{
scanf("%lld%lld%lld", &opt, &x, &y);
if (opt == 0)
split(x, y), printf("%lld\n", sum[x]);
if (opt == 1)
link(x, y);
if (opt == 2)
cut(x, y);
if (opt == 3)
splay(x), val[x] = y;
}
return 0;
}