//Author: Xkien
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define sz(a) (int)a.size()
#define all(a) a.begin(),a.end()
#define ll long long
#define fi first
#define se second
#define il inline
using namespace std;
using namespace __gnu_pbds;
template<class X,class Y>
bool minimize(X &x,const Y &y) {
if (x>y) {
x=y;
return true;
}
return false;
}
template<class X,class Y>
bool maximize(X &x,const Y &y) {
if (x<y) {
x=y;
return true;
}
return false;
}
//ACTUAL CODE HERE
const int maxn=2e5+5;
struct node{
int len;
ll sum_xor;
ll pref_xor;
ll suf_xor;
ll range_xor;
};
node make_node(const node &a, const node &b) {
node c;
c.len=a.len+b.len;
c.sum_xor=a.sum_xor ^ b.sum_xor;
ll val1=(b.len&1 ? a.sum_xor : 0);
c.pref_xor=a.pref_xor ^ val1 ^ b.pref_xor;
ll val2=(a.len&1 ? b.sum_xor : 0);
c.suf_xor=b.suf_xor ^ val2 ^ a.suf_xor;
ll val3=(b.len&1 ? a.suf_xor : 0);
ll val4=(a.len&1 ? b.pref_xor : 0);
c.range_xor = a.range_xor ^ b.range_xor ^ val3 ^ val4;
return c;
}
node st[4*maxn];
void update(int id,int l,int r,int p,int val) {
if (l==r) {
st[id].len=1;
st[id].sum_xor=val;
st[id].pref_xor=val;
st[id].suf_xor=val;
st[id].range_xor=val;
return;
}
int mid=l+r >>1;
if (p<=mid) update(id*2,l,mid,p,val);
else update(id*2+1,mid+1,r,p,val);
st[id]=make_node(st[id*2],st[id*2+1]);
}
node get(int id,int l,int r,int u,int v) {
node c;
c.len=c.sum_xor=c.pref_xor=c.suf_xor=c.range_xor=0;
if (r<u||v<l) return c;
if (u<=l&&r<=v) {
return st[id];
}
int mid=l+r >>1;
return make_node(get(id*2,l,mid,u,v),get(id*2+1,mid+1,r,u,v));
}
int A[maxn];
int n,q;
void solve() {
cin>>n>>q;
for(int i=1;i<=n;++i) {
cin>>A[i];
update(1,1,n,i,A[i]);
}
while(q--) {
int type;cin>>type;
if (type==1) {
int p,val;cin>>p>>val;
update(1,1,n,p,val);
}
else {
int l,r;cin>>l>>r;
ll ans=get(1,1,n,l,r).range_xor;
cout<<ans<<'\n';
}
}
}
signed main() {
freopen("XORanges.inp","r",stdin);
freopen("XORanges.out","w",stdout);
ios_base::sync_with_stdio(0);cin.tie(0);
int t=1;
//cin>>t;
while(t--) solve();
}