#include <bits/stdc++.h>
using namespace std;
const int mxn=3e5+5;
vector<int>a(mxn);
template<typename T>
struct segtree {
	const int n;
    vector<T> stree;
    segtree(int n) : n(n), stree(4*n) {}
    void build(int id,int l,int r){//build segment tree
		if(r-l<2){
			stree[id]=a[l];
			return;
		}
		int mid=(l+r)/2;
		build(2*id,l,mid);
		build(2*id+1,mid,r);
		stree[id]=stree[2*id]^stree[2*id+1];
	}
	void modify(int p,T x,int id,int l,int r){//here we change pth position to x(0-based)
		stree[id]^=x;
		if(r-l<2){
			a[p]=x;
			return;
		}
		int mid=(l+r)/2;
		if(mid>p)
		return modify(p,x,2*id,l,mid);
		else
		return modify(p,x,2*id+1,mid,r);
	}
	T query(int x,int y,int id,int l,int r){//sum from x to y
		if(x >= r or l >= y)	return 0;
		if(x <= l && r <= y)	return stree[id];
		int mid = (l+r)/2;
		return query(x, y, id * 2, l, mid)^query(x, y, id * 2 + 1, mid, r);
	}
};
int main() {
	int i,n,q;
	cin>>n>>q;
	for(i=0;i<n;i++)
	cin>>a[i];
    segtree<int>st(n+1);
    st.build(1,0,n+1);
    for (i=0;i<q;i++) {
		int c,x,y;
		cin>>c;
		if(c==1){
			cin>>x>>y;
			st.modify(x-1,y,1,0,n+1);
		}
		else{
			cin>>x>>y;
			cout<<st.query(x-1,y,1,0,n+1)<<'\n';
		}
		
    }
}

#include <vector>
#include <array>
#include <stack>
#include <queue>
#include <list>
#include <bitset>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
#include <numeric>
#include <iostream>
#include <iomanip>
#include <string>
#include <chrono>
#include <random>
#include <cmath>
#include <cassert>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <functional>
#include <sstream>

using namespace std;


int main(int argc, char** argv) {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout << fixed << setprecision(12);

    int n;
    cin >> n;
    int m;
    cin >> m;
    vector<int> A(m);
    vector<int> B(m);
    vector<int> C(m);

    for (int i = 0; i < m; ++i) {
        cin >> A[i] >> B[i] >> C[i];
        --A[i], --B[i];
    }

    vector<vector<int>> graph(n);
    vector<vector<int>> rgraph(n);
    for (int i = 0; i < m; ++i) {
        int u = A[i];
        int v = B[i];
        graph[u].push_back(i);
        rgraph[v].push_back(i);
    }

    const long long INF = 1LL << 40;
    vector<long long> dis(n, INF);
    using PII = pair<long long,int>;
    priority_queue<PII, vector<PII>, greater<PII>> pq;
    auto dijkstra = [&](int s) -> long long {
        fill(dis.begin(), dis.end(), INF);
        dis[s] = 0;
        pq.emplace(0, s);
        while (!pq.empty()) {
            int u = pq.top().second;
            auto d = pq.top().first;
            pq.pop();
            if (d != dis[u]) {
                continue;
            }
            for (auto e : graph[u]) {
                int v = B[e];
                long long w = C[e];
                if (dis[v] > d + w) {
                    dis[v] = d + w;
                    pq.emplace(dis[v], v);
                }
            }
        }


        long long res = INF;

        for (auto e : rgraph[s]) {
            int v = A[e];
            long long w = C[e];
            res = min(res, dis[v] + w);
        }

        if (res >= INF) {
            return -1;
        }
        return res;
    };


    for (int i = 0; i < n; ++i) {
        cout << dijkstra(i) << '\n';
    }

    return 0;
}