#include <bits/stdc++.h>
using namespace std;
const int Imx = 2147483647;
const long long Lbig = 2e18;
const int mod = 1e9 + 7;
struct fastio {
  char s[100000];
  int it, len;
  fastio() { it = len = 0; }
  inline char get() {
    if (it < len) return s[it++];
    it = 0;
    len = fread(s, 1, 100000, stdin);
    if (len == 0)
      return EOF;
    else
      return s[it++];
  }
  bool notend() {
    char c = get();
    while (c == ' ' || c == '\n') c = get();
    if (it > 0) it--;
    return c != EOF;
  }
} _buff;
inline long long getnum() {
  long long r = 0;
  bool ng = 0;
  char c;
  c = _buff.get();
  while (c != '-' && (c < '0' || c > '9')) c = _buff.get();
  if (c == '-') ng = 1, c = _buff.get();
  while (c >= '0' && c <= '9') r = r * 10 + c - '0', c = _buff.get();
  return ng ? -r : r;
}
template <class T>
inline void putnum(T x) {
  if (x < 0) putchar('-'), x = -x;
  register short a[20] = {}, sz = 0;
  while (x) a[sz++] = x % 10, x /= 10;
  if (sz == 0) putchar('0');
  for (int i = sz - 1; i >= 0; i--) putchar('0' + a[i]);
}
inline char getreal() {
  char c = _buff.get();
  while (c == ' ' || c == '\n') c = _buff.get();
  return c;
}
struct node {
  unsigned int a[32];
  int tn, lazy;
  void init() {
    tn = lazy = 0;
    memset(a, 0, sizeof(a));
  }
  node() { init(); }
  void insert(unsigned int v) {
    if (tn == 32) return;
    for (int i = tn - 1; i >= 0; i--) {
      if ((v ^ a[i]) < v) v ^= a[i];
    }
    if (!v) return;
    int pos = lower_bound(a, a + tn, v) - a;
    for (int i = tn; i > pos; i--) a[i] = a[i - 1];
    a[pos] = v;
    tn++;
  }
  unsigned int& last() { return a[tn - 1]; }
} a[800111];
node merge(node l, node r) {
  node ret;
  if (l.tn < r.tn) {
    ret = r;
    for (int i = 0; i < l.tn; i++) ret.insert(l.a[i]);
  } else {
    ret = l;
    for (int i = 0; i < r.tn; i++) ret.insert(r.a[i]);
  }
  ret.lazy = 0;
  return ret;
}
void pushdown(int p) {
  int& v = a[p].lazy;
  if (v != 0) {
    a[p << 1].lazy ^= v;
    a[p << 1].last() ^= v;
    a[p << 1 | 1].lazy ^= v;
    a[p << 1 | 1].last() ^= v;
    v = 0;
  }
}
unsigned int ia[200111];
void build(int l, int r, int p = 1) {
  if (l == r) {
    a[p].tn = 1;
    a[p].a[0] = ia[l];
    return;
  }
  int m = l + r >> 1;
  build(l, m, p << 1);
  build(m + 1, r, p << 1 | 1);
  a[p] = merge(a[p << 1], a[p << 1 | 1]);
}
node query(int x, int y, int l, int r, int p = 1) {
  if (x <= l && r <= y) return a[p];
  pushdown(p);
  int m = l + r >> 1;
  if (x <= m && m < y)
    return merge(query(x, y, l, m, p << 1), query(x, y, m + 1, r, p << 1 | 1));
  else if (x <= m)
    return query(x, y, l, m, p << 1);
  else
    return query(x, y, m + 1, r, p << 1 | 1);
}
void modify(int x, int y, int v, int l, int r, int p = 1) {
  if (x <= l && r <= y) {
    a[p].lazy ^= v;
    a[p].last() ^= v;
    return;
  }
  pushdown(p);
  int m = l + r >> 1;
  if (x <= m) modify(x, y, v, l, m, p << 1);
  if (m < y) modify(x, y, v, m + 1, r, p << 1 | 1);
  a[p] = merge(a[p << 1], a[p << 1 | 1]);
}
const long long MSK = (1ll << 31) - 1;
void out(int l, int r, int p = 1) {
  cerr << l << "," << r << " " << a[p].lazy << " " << a[p].tn << " "
       << (a[p].last() & MSK) << endl;
  if (l == r) return;
  int m = l + r >> 1;
  out(l, m, p << 1);
  out(m + 1, r, p << 1 | 1);
}
int n, q;
int main() {
  n = getnum(), q = getnum();
  for (int i = 1; i <= n; i++) ia[i] = getnum(), ia[i] |= 1ll << 31;
  build(1, n, 1);
  for (int i = 1; i <= q; i++) {
    int t, x, y, v;
    t = getnum(), x = getnum(), y = getnum();
    if (t == 1) {
      v = getnum();
      modify(x, y, v, 1, n);
    } else {
      node tmp = query(x, y, 1, n), cur;
      for (int i = 0; i < tmp.tn; i++) {
        cur.insert(tmp.a[i] & MSK);
      }
      putnum(1ll << cur.tn), putchar('\n');
    }
  }
  return 0;
}
