#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
int readint() {
  int x = 0, f = 1;
  char s = getchar();
  while (s < '0' || s > '9') {
    if (s == '-') f = -1;
    (s = getchar());
  }
  while (s >= '0' && s <= '9') {
    x = (x << 3) + (x << 1) + (s ^ 48);
    (s = getchar());
  }
  return x * f;
}
struct xxj {
  int p[30], lazy, st;
  void init() {
    memset(p, 0, sizeof(p));
    lazy = 0;
    st = 0;
  }
  int getcnt() {
    int ans = 0;
    for (int i = 0; i <= 29; i++) {
      if (p[i]) ans++;
    }
    return ans;
  }
  void add(int x) {
    for (int i = 29; i >= 0; i--) {
      if ((x >> i) & 1) {
        if (p[i])
          x ^= p[i];
        else {
          p[i] = x;
          break;
        }
      }
    }
  }
} tr[8 * maxn], ans;
xxj merge(const xxj &a, const xxj &b) {
  xxj ans;
  ans.init();
  for (int i = 0; i <= 29; i++) {
    ans.add(b.p[i]);
    ans.add(a.p[i]);
  }
  ans.add(b.st ^ a.st);
  ans.st = a.st;
  return ans;
}
void pushdown(int num) {
  if (tr[num].lazy) {
    tr[num << 1].lazy ^= tr[num].lazy;
    tr[num << 1].st ^= tr[num].lazy;
    tr[num << 1 | 1].lazy ^= tr[num].lazy;
    tr[num << 1 | 1].st ^= tr[num].lazy;
    tr[num].lazy = 0;
  }
}
void build(int l, int r, int num) {
  tr[num].init();
  if (l == r) {
    tr[num].st = readint();
    return;
  }
  int mid = (l + r) >> 1;
  build(l, mid, num << 1);
  build(mid + 1, r, num << 1 | 1);
  tr[num] = merge(tr[num << 1], tr[num << 1 | 1]);
}
void update(int l, int r, int num, int L, int R, int d) {
  if (l >= L && r <= R) {
    tr[num].lazy ^= d;
    tr[num].st ^= d;
    return;
  }
  pushdown(num);
  int mid = (l + r) >> 1;
  if (L <= mid) update(l, mid, num << 1, L, R, d);
  if (R > mid) update(mid + 1, r, num << 1 | 1, L, R, d);
  tr[num] = merge(tr[num << 1], tr[num << 1 | 1]);
}
void Query(int l, int r, int num, int L, int R) {
  if (l >= L && r <= R) {
    ans = merge(tr[num], ans);
    return;
  }
  pushdown(num);
  int mid = (l + r) >> 1;
  if (L <= mid) Query(l, mid, num << 1, L, R);
  if (R > mid) Query(mid + 1, r, num << 1 | 1, L, R);
  tr[num] = merge(tr[num << 1], tr[num << 1 | 1]);
}
int main() {
  int n = readint(), q = readint();
  build(1, n, 1);
  while (q--) {
    int op = readint();
    if (op == 1) {
      int l = readint(), r = readint(), d = readint();
      update(1, n, 1, l, r, d);
    } else {
      int l = readint(), r = readint();
      ans.init();
      Query(1, n, 1, l, r);
      printf("%d\n", 1 << ans.getcnt());
    }
  }
  return 0;
}
