#include<bits/stdc++.h>
using namespace std;
typedef long long int lli;
void update(lli index,lli value,lli BIT[],lli n)
{
    for(;index<=n;index+=(index&(-index)))
    {
        BIT[index]^=value;
    }
}
lli query(lli index,lli BIT[])
{
    lli sum=0;
    for(;index>0;index-=(index&(-index)))
    {
        sum^=BIT[index];
    }
    return sum;
}
int main(){
	ios_base::sync_with_stdio(false);  cin.tie(NULL); //cout.tie(NULL);
	#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin); 
	freopen("error.txt", "w", stderr); 
	freopen("output.txt", "w", stdout); 
	#endif
	long long i,j,t=1;	//cin>>t;
	while(t--){
		lli n,q;
	    cin>>n>>q;
	    lli a[n+1];
	    lli BIT[n+1]={0};
	    for(lli i=1;i<=n;i++)
	    {
	        cin>>a[i];
	        update(i,a[i],BIT,n);
	    }
	    //for(int i=1;i<=n;i++)
	    //cout<<query(i,BIT)<<endl;
	    while(q--)
	    {
	        lli t,x,y;
	        cin>>t>>x>>y;
	        if(t==1)
	        {
	            update(x,y,BIT,n);
	        }
	        if(t==2)
	        {
	            lli z=query(y,BIT)^query(x-1,BIT);
	            cout<<z<<endl;
	        }
    	}
	}
	return 0;
}
#include <bits/stdc++.h>
#define _overload3(_1, _2, _3, name, ...) name
#define _rep(i, n) repi(i, 0, n)
#define repi(i, a, b) for (int i = (int)(a); i < (int)(b); ++i)
#define rep(...) _overload3(__VA_ARGS__, repi, _rep, )(__VA_ARGS__)
#define ll long long
#define lld long double
#ifdef DEBUG
#define line() cout << "[" << __LINE__ << "] ";
#define dump(i) cout << #i ": " << i << " ";
#define dumpl(i) cout << #i ": " << i << endl;
#else
#define line(i)
#define dump(i)
#define dumpl(i)
#endif
using namespace std;

template <typename Monoid>

struct SegmentTree
{
    using F = function<Monoid(Monoid, Monoid)>;
    int sz;
    vector<Monoid> seg;

    const F f;
    const Monoid M1;

    SegmentTree(int n, const F f, const Monoid &M1) : f(f), M1(M1)
    {
        sz = 1;
        while (sz < n)
            sz *= 2;
        seg.assign(2 * sz, M1);
    }
    void set(int k, const Monoid &x)
    {
        seg[k + sz] = x;
    }
    void build()
    {
        for (int k = sz - 1; k > 0; k++)
        {
            seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]);
        }
    }
    void update(int k, const Monoid &x)
    {
        k += sz;
        seg[k] = x;
        while (k >>= 1)
        {
            seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]);
        }
    }
    Monoid query(int a, int b)
    {
        Monoid L = M1, R = M1;
        for (a += sz, b += sz; a < b; a >>= 1, b >>= 1)
        {
            if (a & 1)
                L = f(L, seg[a++]);
            if (b & 1)
                R = f(seg[--b], R);
        }
        return f(L, R);
    }
    Monoid operator[](const int &k) const
    {
        return seg[k + sz];
    }
};

int f(int a, int b)
{
    return a ^ b;
}

int main()
{
    int N, Q;
    cin >> N >> Q;
    SegmentTree<int> seg(N, f, 0);
    rep(i, N)
    {
        int tmp;
        cin >> tmp;
        seg.update(i, tmp);
    }
    rep(i, Q)
    {
        int t, x, y;
        cin >> t >> x >> y;
        if (t == 1)
        {
            x--;
            seg.update(x, seg.query(x, x + 1) ^ y);
        }
        else
        {
            x--;
            y--;
            cout << seg.query(x, y + 1) << endl;
        }
    }
    return 0;
}