#include <bits/stdc++.h>
using namespace std;
long long rdtsc() {
  long long tmp;
  asm("rdtsc" : "=A"(tmp));
  return tmp;
}
inline int myrand() { return abs((rand() << 15) ^ rand()); }
inline int rnd(int x) { return myrand() % x; }
const int INF = (int)1.01e9;
const long double EPS = 1e-9;
void precalc() {}
const int maxn = (int)2e5 + 10, maxq = (int)4e4 + 10;
int n, q;
int a[maxn];
int types[maxn], ls[maxn], rs[maxn], vals[maxn];
bool read() {
  if (scanf("%d%d", &n, &q) < 2) {
    return 0;
  }
  for (int i = 0; i < n; ++i) {
    scanf("%d", a + i);
  }
  for (int i = 0; i < q; ++i) {
    scanf("%d%d%d", types + i, ls + i, rs + i);
    --ls[i];
    if (types[i] == 1) {
      scanf("%d", vals + i);
    }
  }
  return 1;
}
const int maxk = 31;
int mprev[maxk * 2];
int used[maxk * 2];
void gauss(int n, int *a, int &res, int *ans) {
  for (int i = 0; i < n; ++i) {
    mprev[i] = a[i];
    used[i] = 0;
  }
  res = 0;
  for (int c = 0; c < maxk; ++c) {
    int v = -1;
    for (int i = 0; i < n; ++i) {
      if (used[i]) {
        continue;
      }
      if ((a[i] >> c) & 1) {
        v = i;
        break;
      }
    }
    if (v == -1) {
      continue;
    }
    ans[res++] = mprev[v];
    used[v] = 1;
    for (int i = v + 1; i < n; ++i) {
      if ((a[i] >> c) & 1) {
        a[i] ^= a[v];
      }
    }
  }
}
int tmpn;
int tmp[maxk * 2];
struct T {
  int a[maxk];
  int n;
  T() : n(0) {}
  T(int x) {
    n = 1;
    a[0] = (x ^ (1 << 30));
  }
  T(const T &l, const T &r) {
    int &k = tmpn;
    int *b = tmp;
    k = 0;
    for (int i = 0; i < l.n; ++i) {
      b[k++] = l.a[i];
    }
    for (int i = 0; i < r.n; ++i) {
      b[k++] = r.a[i];
    }
    gauss(k, b, n, a);
    assert(n <= maxk);
  }
  void add(int x) {
    for (int i = 0; i < n; ++i) {
      a[i] ^= x;
    }
  }
};
struct SegmTree {
  const static int maxn = (1 << 18);
  T a[maxn * 2];
  int b[maxn * 2];
  int n;
  void build(int _n, int *_a) {
    for (n = 1; n < _n; n <<= 1)
      ;
    assert(n <= maxn);
    for (int i = 0; i < n; ++i) {
      a[n + i] = (i < _n ? T(_a[i]) : T());
      b[n + i] = 0;
    }
    for (int i = n - 1; i; --i) {
      a[i] = T(a[2 * i], a[2 * i + 1]);
      b[i] = 0;
    }
  }
  void push(int v) {
    if (!b[v]) {
      return;
    }
    for (int it = 0; it < 2; ++it) {
      int u = 2 * v + it;
      a[u].add(b[v]);
      b[u] ^= b[v];
    }
    b[v] = 0;
  }
  void add(int v, int l, int r, int l0, int r0, int x) {
    if (l >= r0 || l0 >= r) {
      return;
    }
    if (l0 <= l && r <= r0) {
      a[v].add(x);
      b[v] ^= x;
      return;
    }
    push(v);
    int m = (l + r) / 2;
    add(2 * v, l, m, l0, r0, x);
    add(2 * v + 1, m, r, l0, r0, x);
    a[v] = T(a[2 * v], a[2 * v + 1]);
  }
  void add(int l, int r, int x) { add(1, 0, n, l, r, x); }
  T get(int v, int l, int r, int l0, int r0) {
    if (l >= r0 || l0 >= r) {
      return T();
    }
    if (l0 <= l && r <= r0) {
      return a[v];
    }
    push(v);
    int m = (l + r) / 2;
    T le = get(2 * v, l, m, l0, r0);
    T ri = get(2 * v + 1, m, r, l0, r0);
    return T(le, ri);
  }
  T get(int l, int r) { return get(1, 0, n, l, r); }
} tree;
void solve() {
  tree.build(n, a);
  for (int i = 0; i < q; ++i) {
    int type = types[i];
    if (type == 1) {
      tree.add(ls[i], rs[i], vals[i]);
    } else {
      assert(type == 2);
      T res = tree.get(ls[i], rs[i]);
      T got(res, T(0));
      printf("%d\n", (1 << (got.n - 1)));
    }
  }
}
int main() {
  srand(rdtsc());
  precalc();
  while (1) {
    if (!read()) {
      break;
    }
    solve();
  }
  return 0;
}
