#pragma GCC optimize("Ofast")

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define vi vector<int>
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define pb push_back


template<typename T>
class SegTree {
    int n;                       // 葉の数
    vector<T> data;              // データを格納するvector
    T def;                       // 初期値かつ単位元
    function<T(T, T)> operation; // 区間クエリで使う処理
    function<T(T, T)> update;    // 点更新で使う処理
 
    T _query(int a, int b, int k, int l, int r) {
        if (r <= a || b <= l) return def; // 交差しない
        if (a <= l && r <= b)
            return data[k]; // a,l,r,bの順で完全に含まれる
        else {
            T c1 = _query(a, b, 2 * k + 1, l, (l + r) / 2); // 左の子
            T c2 = _query(a, b, 2 * k + 2, (l + r) / 2, r); // 右の子
            return operation(c1, c2);
        }
    }
 
  public:
    SegTree(size_t _n, T _def, function<T(T, T)> _operation,
            function<T(T, T)> _update)
        : def(_def), operation(_operation), update(_update) {
        n = 1;
        while (n < _n) {
            n *= 2;
        }
        data = vector<T>(2 * n - 1, def);
    }
 
    void change(int i, T x) {
        i += n - 1;
        data[i] = update(data[i], x);
        while (i > 0) {
            i = (i - 1) / 2;
            data[i] = operation(data[i * 2 + 1], data[i * 2 + 2]);
        }
    }
 
    T query(int a, int b) {
        return _query(a, b, 0, 0, n);
    }
 
    T operator[](int i) {
        return data[i + n - 1];
    }
};

bool solve()
{
    ll n,q,a,t,x,y;
    cin >> n >> q;
    SegTree<ll> st(n, 0,
        [](ll p, ll k){return p^k;},
        [](ll p, ll k){return p^k;});

    rep(i,n){
        cin >> a;
        st.change(i, a);
    }

    rep(i,q){
        cin >> t >> x >> y;
        x--;
        if(t==1){
            st.change(x, y);
        }
        else{
            cout << st.query(x, y) << endl;
        }
    }

    return true;
}

int main()
{
    solve();
    return 0;
}
#pragma GCC target ("avx2")
//#pragma GCC optimize "trapv"
#pragma GCC optimization ("O3")
#pragma GCC optimization ("unroll-loops")
#include <bits/stdc++.h>
#define input(a,n) for(ll i1=0;i1<n;i1++)cin>>a[i1]
#define ll long long
#define pi 2 * acos(0.0)
#define usll unordered_set<ll>
#define sll set<ll>
#define vll vector<ll>
#define mll map<ll,ll>
#define pll pair<ll,ll>
#define umll unordered_map<ll,ll>
#define S second
#define sz size()
#define all(v) v.begin(),v.end()
#define Y cout<< "YES"<< "\n"
#define N cout<< "NO"<< "\n"
#define F first
#define mp make_pair
#define pb push_back
#define pf push_front
#define ld long double
#define mod 1000000007
using namespace std;
ll st[1200001];
umll m;
void build(ll a[],ll l,ll r,ll i)
{
    if(l==r)
    {
        st[i]=a[l];
        return;
    }
    ll mid=(r-l)/2+l;
    build(a,l,mid,2*i+1);
    build(a,mid+1,r,2*i+2);
    st[i]=(st[2*i+1]^st[2*i+2]);
}
void update(ll l,ll r,ll i,ll ind,ll v)
{
    if(ind<l||ind>r)
        return;
    else if(l==r&&ind==l)
    {
        st[i]=(st[i]^v);
        return;
    }
    ll mid=(r-l)/2+l;
    update(l,mid,2*i+1,ind,v);
    update(mid+1,r,2*i+2,ind,v);
    st[i]=(st[2*i+1]^st[2*i+2]);
}
ll que(ll l,ll r,ll low,ll high,ll i)
{
    if(high<l||low>r)
        return 0;
    else if(l>=low&&r<=high)
        return st[i];
    ll mid=(r-l)/2+l;
    return (que(l,mid,low,high,2*i+1)^que(mid+1,r,low,high,2*i+2));
}
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    for(ll i=0;i<=1200000;i++)
        st[i]=0;
    ll n,q,c,l,r,p;
    cin>>n>>q;
    ll a[n];
    for(ll i=0;i<n;i++)
    {
        cin>>a[i];
    }
    build(a,0,n-1,0);
    //for(ll i=0;i<=10;i++)
      //  cout<<st[i]<< " ";
    //cout<< "\n";
    while(q--)
    {
            cin>>p>>l>>r;
            if(p==1)
            {
                l--;
                update(0,n-1,0,l,r);
            }
            else
            {
                l--;
                r--;
                ll ans=que(0,n-1,l,r,0);
                cout<<ans<< "\n";
            }
    }
    return 0;
}
