#include <bits/stdc++.h>
using namespace std;
namespace INPUT {
const int L = 1 << 20;
char _buf[L], *S, *T, c;
char _gc() {
  if (S == T) {
    T = (S = _buf) + fread(_buf, 1, L, stdin);
    if (S == T) return EOF;
  }
  return *S++;
}
void Readi(int &x) {
  for (c = _gc(); c < '0' || c > '9'; c = _gc())
    ;
  for (x = 0; c >= '0' && c <= '9'; c = _gc())
    x = (x << 3) + (x << 1) + (c & 15);
}
}  // namespace INPUT
using INPUT::Readi;
const int N = 200010, S = 30;
struct basis {
  int v[S + 1];
  void Insert(int val) {
    for (int i = S; i >= 0; i--)
      if ((val >> i) & 1)
        if (v[i])
          val ^= v[i];
        else {
          v[i] = val;
          break;
        }
  }
  int Count() {
    int s = 0;
    for (int i = 0; i <= S; i++) s += v[i] > 0;
    return 1 << s;
  }
} T[N * 4];
basis merge(basis a, basis b) {
  for (int i = 0; i <= S; i++) a.Insert(b.v[i]);
  return a;
}
int n, q, a[N], s[N];
inline int lowbit(int x) { return x & -x; }
void upd(int x, int v) {
  for (; x <= n; x += lowbit(x)) s[x] ^= v;
}
int que(int x) {
  int res = 0;
  for (; x > 0; x -= lowbit(x)) res ^= s[x];
  return res;
}
void build(int k, int l, int r) {
  if (l == r) {
    T[k].Insert(a[l]);
    return;
  }
  int mid = l + r >> 1;
  build(k << 1, l, mid);
  build(k << 1 | 1, mid + 1, r);
  T[k] = merge(T[k << 1], T[k << 1 | 1]);
}
basis query(int k, int L, int R, int l, int r) {
  if (l <= L && R <= r) return T[k];
  int mid = L + R >> 1;
  if (r <= mid) return query(k << 1, L, mid, l, r);
  if (l > mid) return query(k << 1 | 1, mid + 1, R, l, r);
  return merge(query(k << 1, L, mid, l, mid),
               query(k << 1 | 1, mid + 1, R, mid + 1, r));
}
void update(int k, int l, int r, int pos, int v) {
  if (l == r) {
    for (int i = 0; i <= S; i++) T[k].v[i] = 0;
    T[k].Insert(v);
    return;
  }
  int mid = l + r >> 1;
  if (pos <= mid)
    update(k << 1, l, mid, pos, v);
  else
    update(k << 1 | 1, mid + 1, r, pos, v);
  T[k] = merge(T[k << 1], T[k << 1 | 1]);
}
int main() {
  Readi(n);
  Readi(q);
  for (int i = 1; i <= n; i++) Readi(a[i]);
  for (int i = n; i >= 1; i--) a[i] = a[i] ^ a[i - 1], upd(i, a[i]);
  build(1, 1, n);
  int op, l, r, x;
  while (q--) {
    Readi(op);
    Readi(l);
    Readi(r);
    if (op == 1) {
      Readi(x);
      update(1, 1, n, l, a[l] ^= x);
      if (r < n) update(1, 1, n, r + 1, a[r + 1] ^= x);
      upd(l, x);
      upd(r + 1, x);
    } else {
      basis Ans;
      for (int i = 0; i <= S; i++) Ans.v[i] = 0;
      if (l < r) Ans = query(1, 1, n, l + 1, r);
      Ans.Insert(que(l));
      printf("%d\n", Ans.Count());
    }
  }
  return 0;
}
