#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
using namespace std;
const long long mod = 998244353;
struct basis {
  vector<int> v;
  int d;
  int sz;
  basis() {}
  basis(int _d) {
    d = _d;
    v.assign(d, 0);
    sz = 0;
  }
  basis operator=(const basis& oth) {
    vector<int> z(oth.v);
    v.swap(z);
    d = oth.d;
    sz = oth.sz;
    return *this;
  }
  void init(int _d) {
    d = _d;
    v.assign(d, 0);
    sz = 0;
  }
  void insvec(int mask) {
    for (int i = d - 1; i >= 0; i--) {
      if ((mask & 1 << i) == 0) continue;
      if (!v[i]) {
        v[i] = mask;
        ++sz;
        return;
      }
      mask ^= v[i];
    }
  }
  bool present(int x) {
    for (int i = d - 1; i >= 0; i--) {
      if ((x & 1 << i) == 0) continue;
      if (!v[i]) {
        return false;
      }
      x ^= v[i];
    }
    return true;
  }
  int query(int k) {
    int mask = 0;
    int tot = 1 << sz;
    for (int i = d - 1; i >= 0; i--)
      if (v[i]) {
        int hal = tot / 2;
        if ((k <= hal && (mask & 1 << i) == 0) ||
            (k > hal && (mask & 1 << i) > 0))
          mask ^= v[i];
        if (k > hal) k -= hal;
        tot >>= 1;
      }
    return mask;
  }
};
struct item {
  int n;
  basis b;
  item(int x = 0) : n(x) {
    b.init(30);
    if (x != 0) b.insvec(x);
  }
  item operator+(const item& oth) {
    item r;
    r.b = oth.b;
    r.n = n ^ oth.n;
    for (int i = b.d - 1; i >= 0; i--) {
      if (b.v[i]) r.b.insvec(b.v[i]);
    }
    return r;
  }
};
template <class node>
struct segtree {
  int n;
  vector<node> st;
  void init(int _n) {
    n = _n;
    st.assign(2 * n, node());
  }
  inline int le(int x) { return 2 * x + 1; }
  inline int ri(int x) { return 2 * x + 2; }
  void build(vector<int>& a) {
    init(a.size());
    for (int i = n; i < 2 * n; i++) st[i] = a[i - n];
    for (int i = n - 1; i > 0; i--) st[i] = st[i << 1] + st[i << 1 | 1];
  }
  void set(int i, int x) {
    for (st[i += n] = x; i >>= 1;) st[i] = st[i << 1] + st[i << 1 | 1];
  }
  node query(int l, int r) {
    node anl, anr;
    r++;
    for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
      if (l & 1) anl = anl + st[l++];
      if (r & 1) anr = st[--r] + anr;
    }
    return anl + anr;
  }
};
int n, q;
vector<int> b;
int lst, a, tag, l, r, k;
void solve() {
  cin >> n >> q;
  lst = 0;
  b.resize(n);
  for (int i = 0; i < n; i++) {
    cin >> b[i];
    a = b[i];
    b[i] ^= lst;
    lst = a;
  }
  segtree<item> fo;
  fo.init(n);
  fo.build(b);
  while (q--) {
    cin >> tag >> l >> r;
    l--;
    if (tag == 1) {
      cin >> k;
      b[l] = b[l] ^ k;
      fo.set(l, b[l]);
      if (r != n) {
        b[r] = b[r] ^ k;
        fo.set(r, b[r]);
      }
    } else {
      r--;
      a = (fo.query(0, l)).n;
      if (l == r) {
        if (a == 0)
          cout << 1 << '\n';
        else
          cout << 2 << '\n';
        continue;
      }
      item z = fo.query(l + 1, r);
      z.b.insvec(a);
      cout << (1 << z.b.sz) << '\n';
    }
  }
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  int t = 1;
  while (t--) {
    solve();
  }
}
