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

void dfs(int node, int f, auto& g, auto& seen, auto& sol, auto& edges) {
    seen[node] = 1;
    int n = g.size();
    for (int v = 0; v < n; v += 1) {
        if (g[node][v] == 0)
            continue;
        if (v == f) 
            continue;

        int ind = g[node][v] - 1;

        if (seen[v]) {
            if (v == edges[ind].first)
                sol[ind] = 0;
            else
                sol[ind] = 1;
            continue;
        }
        
        if (v == edges[ind].first)
            sol[ind] = 1;
        else
            sol[ind] = 0;
        dfs (v, node, g, seen, sol, edges);
    }
}

int main() {
    int n, m; cin >> n >> m;
    vector<vector<int>> g(n, vector<int> (n, 0));
    vector<pair<int, int>> edges;

    for (int i = 0; i < m; i += 1) {
        int a, b; cin >> a >> b;
        a -= 1, b -= 1;
        edges.push_back(make_pair(a, b));
    }
    
    vector<int> c(n, 0);
    for (int i = 0; i < n; i += 1) {
        cin >> c[i];
    }
    
    vector<int> sol(m, -1);

    for (int i = 0; i < m; i += 1) {
        auto e = edges[i];
        if (c[e.first] < c[e.second]) {
            sol[i] = 1;
        } else if (c[e.first] > c[e.second]) {
            sol[i] = 0;
        } else {
            g[e.first][e.second] = i + 1;
            g[e.second][e.first] = i + 1;
        }
    }
 
    vector<int> seen(n, 0);

    for (int i = 0; i < n; i += 1)
        if (not seen[i]) {
            dfs(i, -1, g, seen, sol, edges);
        }

    for (int i = 0; i < m; i += 1) {
        if (sol[i])
            cout << "<-\n";
        else 
            cout << "->\n";
    }
}
#include <bits/stdc++.h>
#define fi first
#define se second
#define rep(i, s, n) for (int i = (s); i < (n); ++i)
#define rrep(i, n) for (int i = n - 1; i >= 0; --i)
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define len(x) (int)(x).size()
#define pb push_back
#define em emplace_back
#define vi vector<int>
#define vs vector<string>
#define vc vector<char>
#define vd vector<double>
#define vb vector<bool>
#define vvi vector<vector<int>>
#define vvl vector<vector<long long>>
#define fast  \
  cin.tie(0); \
  ios::sync_with_stdio(false);
using namespace std;
using ll = long long;
using ld = long double;
using P = pair<int, int>;

struct RMQ {
  int n;                               // 葉の数
  vector<int> dat;                     // 完全二分木の配列
  RMQ(int n_) : n(), dat(n_ * 4, 0) {  // 葉の数は 2^x の形
    int x = 1;
    while (n_ > x) {
      x *= 2;
    }
    n = x;
  }
  void update(int i, int x) {
    i += n - 1;
    dat[i] = x;
    while (i > 0) {
      i = (i - 1) / 2;  // parent
      dat[i] = dat[i * 2 + 1] ^ dat[i * 2 + 2];
    }
  }
  // the minimum element of [a,b)
  int query(int a, int b) { return query_sub(a, b, 0, 0, n); }
  int query_sub(int a, int b, int k, int l, int r) {
    if (r <= a || b <= l) {
      return 0;
    } else if (a <= l && r <= b) {
      return dat[k];
    } else {
      int vl = query_sub(a, b, k * 2 + 1, l, (l + r) / 2);
      int vr = query_sub(a, b, k * 2 + 2, (l + r) / 2, r);
      return (vl ^ vr);
    }
  }
};

int main() {
  fast;
  int n, q;
  cin >> n >> q;
  vi a(n);
  rep(i, 0, n) cin >> a[i];
  RMQ seg(n);
  rep(i, 0, n) seg.update(i, a[i]);
  rep(i, 0, q) {
    int t, x, y;
    cin >> t >> x >> y;
    if (t == 1) {
      seg.update(x - 1, seg.dat[x + seg.n - 2] ^ y);
    } else {
      cout << seg.query(x - 1, y) << endl;
    }
  }
  return 0;
}