#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
#define rep(i,n) rep2(i,0,n)
#define rep2(i,l,r) for(ll i=(l),i##_len=(r);i<i##_len;i++)
const ll INF = 1LL << 60;

template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }

template <typename T>class segtree{
    typedef function<T(T,T)> F;
    const T _e;
    F fun1,fun2;
    public:
        ll _n;
        vector<T> node;
        //Constructor
        segtree():_n(0){}
        segtree(F resultFunction,ll n,T e):segtree(resultFunction,vector<T>(n,e),e,NULL){}
        segtree(F resultFunction,vector<T> &v,T e):segtree(resultFunction,v,e,NULL){}
        segtree(F resultFunction,vector<T> &v,T e,F changeFunction):fun1(resultFunction),_e(e),fun2(changeFunction){
            ll m=v.size();
            _n=1;
            while(_n<m) _n*=2;
            node.resize(2*_n-1);
            for(ll i=0;i<2*_n-1;i++){
                if(_n-1<=i&&i<_n+m-1) node[i]=v[i-_n+1];
                else node[i]=e;
            }
        }

        //Build//O(N)
        void build(){
            for (ll i = _n - 2; i>= 0; i--){
                node[i] = fun1(node[2 * i + 1], node[2 * i + 2]);
            }
        }

        //Update//O(logN)
        void update(ll num,T x,bool mode){
            num+=_n-1;
            if(mode) node[num]=fun2(node[num],x);
            else node[num]=x;
            while(num>0){
                num=(num-1)/2;//parent
                node[num]=fun1(node[num*2+1],node[num*2+2]);
            }
        }

        //Query//O(logN)
        T query(ll a,ll b){return query_sub(a,b,0,0,_n);}
        T query_sub(ll a,ll b,ll k,ll l,ll r){
            if(r<=a||b<=l) return _e;
            else if(a<=l&&r<=b) return node[k];
            else{
                T vl=query_sub(a,b,2*k+1,l,(l+r)/2);
                T vr=query_sub(a,b,2*k+2,(l+r)/2,r);
                return fun1(vl,vr);
            }
        }
};

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

int main(){
    ll n,q;cin>>n>>q;
    vector<int> a(n);rep(i,n) cin>>a[i];
    segtree<int> seg(f,a,0,f);
    seg.build();
    
    rep(i,q){
        int t,x,y;cin>>t>>x>>y;
        x--;
        if(t==1) seg.update(x,y,1);
        else cout<<seg.query(x,y)<<endl;
    }
}

// Problem : F - Range Xor Query
// Contest : AtCoder - AtCoder Beginner Contest 185
// URL : https://atcoder.jp/contests/abc185/tasks/abc185_f
// Memory Limit : 1024 MB
// Time Limit : 3000 ms
// Powered by CP Editor (https://github.com/cpeditor/cp-editor)

#include <bits/stdc++.h>
using namespace std;

#define SPEED ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define ll long long
#define endl '\n'
#define vi vector<ll>
#define pii pair<ll, ll>
#define pb push_back
#define fi first
#define se second
#define all(x) x.begin(), x.end()
#define fill(a,b) memset(a, b, sizeof(a))
#define setbits(x) __builtin_popcountll(x)

const ll inf=0x3f3f3f3f3f3f3f3f, N = 3e5 + 5;
ll a[N], st[4 * N], n, q;
void build(ll node, ll L, ll R) {
	if(L == R) {
		st[node] = a[L];
		return;
	}
	ll M = (L + R)>>1;
	build(2 * node, L, M);
	build(2 * node + 1, M + 1, R);
	st[node] = st[2 * node] ^ st[2 * node + 1];
}
void update(ll node, ll L, ll R, ll pos, ll y) {
	if(pos < L || pos > R)return;
	if(L == R) {
		a[L] ^= y;
		st[node] ^= y;
		return;
	}
	ll M = (L + R)>>1;
	update(2 * node, L, M, pos, y);
	update(2 * node + 1, M + 1, R, pos, y);
	st[node] = st[2 * node] ^ st[2 * node + 1];
}
ll query(ll node, ll L, ll R, ll l, ll r) {
	if(L > r || l > R)return 0;
	if(l <= L && r >= R)return st[node];
	ll M = (L + R)>>1;
	return (query(2 * node, L, M, l, r) ^ query(2 * node + 1, M + 1, R, l, r));
}
int main() {
    SPEED;
    cin>>n>>q;
    for(ll i = 1; i <= n; i++)cin>>a[i];
    build(1, 1, n);
    while(q--) {
    	ll t, x, y;
    	cin>>t>>x>>y;
    	if(t == 1)update(1, 1, n, x, y);
    	else cout<<query(1, 1, n, x, y)<<endl;
    }
    return 0;
}