#include <bits/stdc++.h>
using namespace std;
int read() {
  int number = 0, c = getchar();
  for (; !(c > 47 && c < 58); c = getchar())
    ;
  for (; (c > 47 && c < 58); c = getchar())
    number = (number << 3) + (number << 1) + c - 48;
  return number;
}
const int N = 200005;
struct Node {
  int M[31], rows, cnt;
  Node() {
    rows = cnt = 0;
    memset(M, 0, sizeof M);
  }
  Node(int x) {
    memset(M, 0, sizeof M);
    rows = 0, cnt = (x > 0);
    M[0] = x | (1 << 30);
  }
  void Modify(int x) {
    cnt = 0;
    for (int i = 0; i < 31; ++i) M[i] ^= x * ((M[i] >> 30) & 1);
    int currow = 0;
    for (int i = 0; i < 31; ++i) {
      int idx = -1;
      for (int j = currow; j < 31; ++j)
        if ((M[j] >> i) & 1) {
          idx = j;
          break;
        }
      if (idx == -1) continue;
      swap(M[currow], M[idx]);
      for (int j = 0; j < 31; ++j)
        if ((j != currow) && ((M[j] >> i) & 1)) M[j] ^= M[currow];
      cnt += (i < 30);
      currow++;
    }
  }
} t[N << 2];
int cur[62];
Node Merge(const Node a, const Node b) {
  Node x = Node();
  for (int i = 0; i < 31; ++i) cur[i] = a.M[i], cur[i + 31] = b.M[i];
  for (int i = 0, l = 0; i < 31; ++i) {
    int idx = -1;
    for (int j = l; j < 62; ++j)
      if ((cur[j] >> i) & 1) {
        idx = j;
        break;
      }
    if (idx == -1) continue;
    swap(cur[l], cur[idx]);
    for (int j = 0; j < 62; ++j)
      if ((j != l) && ((cur[j] >> i) & 1)) cur[j] ^= cur[l];
    x.cnt += (i < 30), ++l;
  }
  for (int i = 0; i < 62; ++i)
    if (cur[i]) x.M[x.rows++] = cur[i];
  return x;
}
int a[N], lz[N << 2];
void Init(int node, int l, int r) {
  if (l == r) {
    t[node] = Node(a[l]);
    return;
  }
  Init(node << 1, l, ((l + r) >> 1));
  Init(node << 1 | 1, ((l + r) >> 1) + 1, r);
  t[node] = Merge(t[node << 1], t[node << 1 | 1]);
}
void down(int node, int l, int r) {
  if (lz[node] == 0) return;
  int y = lz[node];
  lz[node] = 0;
  t[node].Modify(y);
  if (l != r) {
    lz[node << 1] ^= y;
    lz[node << 1 | 1] ^= y;
  }
}
void update(int node, int l, int r, int u, int v, int val) {
  down(node, l, r);
  if (r < u || v < l) return;
  if (u <= l && r <= v) {
    lz[node] ^= val;
    down(node, l, r);
    return;
  }
  update(node << 1, l, ((l + r) >> 1), u, v, val);
  update(node << 1 | 1, ((l + r) >> 1) + 1, r, u, v, val);
  t[node] = Merge(t[node << 1], t[node << 1 | 1]);
}
Node get(int node, int l, int r, int u, int v) {
  down(node, l, r);
  if (r < u || v < l) return Node();
  if (u <= l && r <= v) return t[node];
  return Merge(get(node << 1, l, ((l + r) >> 1), u, v),
               get(node << 1 | 1, ((l + r) >> 1) + 1, r, u, v));
}
int main() {
  int n = read(), q = read();
  for (int i = 1; i <= n; a[i++] = read())
    ;
  Init(1, 1, n);
  while (q--) {
    int type = read(), l = read(), r = read();
    if (type == 1) {
      int val = read();
      update(1, 1, n, l, r, val);
    } else {
      printf("%d\n", 1 << get(1, 1, n, l, r).cnt);
    }
  }
}
