#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<sstream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<cmath>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<numeric>
#include<functional>
#include<algorithm>
#include<bitset>
#include<tuple>
#include<unordered_set>
#include<unordered_map>
#include<random>
#include<array>
#include<cassert>
using namespace std;
#define INF ((1<<30)-1)
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define all(v) v.begin(),v.end()


class BIT {
	int lg;
	std::vector<int> bit;
public:
	BIT(int size) :bit(size + 1, 0) {
		lg = size;
		while (lg & lg - 1)lg &= lg - 1;
	}
	void add(int i, int x) {
		i++;
		while (i < (int)bit.size()) {
			bit[i] ^= x;
			i += i & -i;
		}
	}
	int sum(int a)const {
		a++;
		int res = 0;
		while (0 < a) {
			res ^= bit[a];
			a -= a & -a;
		}
		return res;
	}
};

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	int n, q;
	cin >> n >> q;
	BIT bit(n);
	rep(i, n) {
		int a;
		cin >> a;
		bit.add(i, a);
	}


	rep(_, q) {
		int t, x, y;
		cin >> t >> x >> y;
		if (t==1) {
			bit.add(x - 1, y);
		}
		else {
			int ans = bit.sum(y - 1);
			if (1 < x)ans ^= bit.sum(x - 2);
			cout << ans << endl;
		}
	}



	return 0;
}

#include<bits/stdc++.h> 
#include <ext/pb_ds/assoc_container.hpp> 
#include <ext/pb_ds/tree_policy.hpp> 
using namespace std;
using namespace __gnu_pbds;  
#define ordered_set tree<ll, null_type , less<ll> , rb_tree_tag , tree_order_statistics_Node_update> 
#define ll long long
#define ull unsigned long long
#define pb push_back
#define inf 3e18
#define mk make_pair
#define ld long double
#define mod 1000000007 
#define fi first
#define se second
#define fastIO ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define test ll t; cin>>t; while(t--)
#define setbits __builtin_popcount
#define endl '\n'
#define LOCAL
#define sim template < class c
#define ris return * this
#define dor > debug & operator <<
#define eni(x) sim > typename \
enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim > struct rge { c b, e; };
sim > rge<c> range(c i, c j) { return rge<c>{i, j}; }
sim > auto dud(c* x) -> decltype(cerr << *x, 0);
sim > char dud(...);
struct debug {
#ifdef LOCAL
~debug() { cerr << endl; }
eni(!=) cerr << boolalpha << i; ris; }
eni(==) ris << range(begin(i), end(i));}
sim, class b dor(pair < b, c > d) {
    ris << "(" << d.first << ", " << d.second << ")";
}
sim dor(rge<c> d) {
    *this << "[";
    for (auto it = d.b; it != d.e; ++it)
        *this << ", " + 2 * (it == d.b) << *it;
    ris << "]";
}
#else
sim dor(const c&) { ris; }
#endif
};
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "
#define maxn 300001
vector<ll>a(maxn);
ll seg[4*maxn];
void build(ll v,ll l,ll r)
{
	if(l==r)
	{
		seg[v]=a[l];
		return;
	}
	ll mid=(l+r)/2;
	build(2*v,l,mid);
	build(2*v+1,mid+1,r);
	seg[v]=seg[2*v]^seg[2*v+1];
}
void update(ll v,ll l,ll r,ll pos,ll val)
{
	if(l==r)
	{
		seg[v]^=val;
		return;
	}
	ll mid=(l+r)/2;
	if(pos<=mid)
	{
		update(2*v,l,mid,pos,val);
	}
	else
	{
		update(2*v+1,mid+1,r,pos,val);
	}
	seg[v]=seg[2*v]^seg[2*v+1];
}
ll query(ll v,ll l,ll r,ll x,ll y)
{
	if(y<x)
	{
		return 0;
	}
	if(x<=l && r<=y)
	{
		return seg[v];
	}	
	ll mid=(l+r)/2,val,val1;
	val=query(2*v,l,mid,x,min(y,mid));
	val1=query(2*v+1,mid+1,r,max(mid+1,x),y);
	return val^val1;
}
int main()
{
	fastIO;
	ll n,q;
	cin>>n>>q;
	for(int i=0;i<n;i++)
	{
		cin>>a[i];
	}
	build(1,0,n-1);
	ll x,y,z,val;
	while(q--)
	{
		cin>>x>>y>>z;
		if(x==1)
		{
			y--;
			update(1,0,n-1,y,z);
		}
		else
		{
			y--;
			z--;
			val=query(1,0,n-1,y,z);
			cout<<val<<endl;
		}
	}
}