#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back
using namespace std;
using ll = long long int;
template<typename T>
ostream& operator+(ostream& out, const vector<T> &vec){
    for(const auto &x : vec){
        out<<x<<" ";
    }
    out<<"\n";
    return out;
}
template<typename T>
ostream& operator*(ostream& out, const vector<T> &vec){
    for(const auto &x : vec){
        out+x;
    }
    return out;
}
template<typename T>
istream& operator>>(istream& in, vector<T> &vec){
    for(auto &x : vec){
        in>>x;
    }
    return in;
}
template<typename T>
struct segment_tree {
    int n;
    vector<T> segtree;
    function<T(const T&,const T&)> join;
    T base = T();
    segment_tree(int n, function<T(const T&,const T&)> join, T base = T()) : n(n), join(join), base(base){
        segtree.resize(n << 1, base);
    }
    void build() {
        for (int i = n - 1; i > 0; --i) {
            segtree[i] = join(segtree[(i << 1)], segtree[(i << 1) | 1]);
        }
    }
    segment_tree(vector<T> seq, function<T(const T&,const T&)> join, T base = T()) : n(seq.size()), join(join), base(base){
        segtree.resize(n << 1, base);
        for (int i = 0; i < n; i++) {
            segtree[n + i] = seq[i];
        }
        build();
    }
    void calc(int pos){
        pos >>= 1;
        while (pos) {
            segtree[pos] = join(segtree[pos << 1], segtree[(pos << 1) | 1]);
            pos >>= 1;
        }
    }
    void set(int pos, T val){
        pos+=n;
        segtree[pos] = val;
        calc(pos);
    }
    void increment(int pos, T val){
        pos+=n;
        segtree[pos] = join(segtree[pos], val);
        calc(pos);
    }
    T query(int l, int r) {
        T ansl = base;
        T ansr = base;
        l += n;
        r += n + 1;
        while (l < r) {
            if (l & 1) {
                ansl = join(ansl, segtree[l++]);
            }
            if (r & 1) {
                ansr = join(segtree[--r], ansr);
            }
            l >>= 1;
            r >>= 1;
        }
        return join(ansl, ansr);
    }
};
void solve(){
    int n,q;
    cin>>n>>q;
    vector<int> seq(n);
    cin>>seq;
    segment_tree<int> st(seq, [&](int x,int y){
        return x^y;
    }, 0);
    for(int i=0;i<q;i++){
        int t;
        cin>>t;
        if(t == 1){
            int idx,y;
            cin>>idx>>y;
            --idx;
            st.increment(idx, y);
        }
        else{
            int l,r;
            cin>>l>>r;
            --l;--r;
            cout<<st.query(l,r)<<"\n";
        }
    }
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    solve();
}
#include <bits/stdc++.h>
using namespace std;
#define int long long int

int A[300005];
int P[300005];
int SQ[605];
int N,Q;

int32_t main(){
	cin>>N>>Q;
	for(int i=1;i<=N;i++){
		cin>>A[i];
		P[i] = P[i-1]^A[i];
		if(i%500 == 0){
			SQ[i/500] = P[i]^P[i-500];
		}
	}
	// SQ[i] = A[(i-1)*500+1]^A[(i-1)*500+2]^...^A[i*500]
	int maxb = N/500;
	int T,X,Y;
	for(int i=1;i<=Q;i++){
		cin>>T>>X>>Y;
		if(T==1){
			A[X] ^= Y;
			SQ[(X-1)/500+1] ^= Y;
		}
		else {
			int ans = 0;
			int xb = (X-1)/500 + 1;
			int yb = (Y-1)/500 + 1;
			if(xb == yb){
				for(int j=X;j<=Y;j++){
					ans ^= A[j];
				}
			}
			else {
				for(int j=X;j<=xb*500;j++){
					ans ^= A[j];
				}
				for(int j=xb+1;j<yb;j++){
					ans ^= SQ[j];
				}
				for(int j=(yb-1)*500+1;j<=Y;j++){
					ans ^= A[j];
				}
			}
			cout<<ans<<"\n";
		}
	}
}