#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-all-loops")
using namespace std;
const int MAXBUF = 1 << 23;
char B[MAXBUF], *Si = B, *Ti = B;
inline char getc() {
  if (Si == Ti) Ti = (Si = B) + fread(B, 1, MAXBUF, stdin);
  if (Si == Ti)
    return 0;
  else
    return *Si++;
}
template <class T>
inline void read(T &a) {
  static char c;
  static int fh;
  while (((c = getc()) < '0' || c > '9') && c != '-')
    ;
  if (c == '-')
    fh = -1, a = 0;
  else
    fh = 1, a = c - '0';
  while ((c = getc()) <= '9' && c >= '0') a = (a << 3) + (a << 1) + c - '0';
  if (fh == -1) a = -a;
}
char Buff[MAXBUF], *sti = Buff;
template <class T>
inline void write(T a) {
  if (a == 0) {
    *sti++ = '0';
    return;
  }
  if (a < 0) *sti++ = '-', a = -a;
  static char c[20];
  static int c0;
  c0 = 0;
  while (a) c[c0++] = a % 10 + '0', a /= 10;
  while (c0--) *sti++ = c[c0];
}
struct base {
  int b[31], sz;
} t[550005], ans;
int a[200005], b[200005], n, q;
int w[200005];
inline void add(int pos, int del) {
  while (pos <= n) {
    w[pos] ^= del;
    pos += (pos & (-pos));
  }
}
inline int ask(int pos) {
  int s = 0;
  while (pos) {
    s ^= w[pos];
    pos -= (pos & (-pos));
  }
  return s;
}
inline void merge(base &p, base q) {
  if (p.sz == 30) return;
  for (register int i = 29; i >= 0; i--) {
    if (q.b[i]) {
      int num = q.b[i];
      for (register int j = i; j >= 0; j--) {
        if (num & (1 << j)) {
          if (!p.b[j]) {
            p.b[j] = num;
            p.sz++;
            break;
          }
          num ^= p.b[j];
        }
      }
    }
  }
}
void build(int pos, int l, int r) {
  if (l == r) {
    for (int i = 29; i >= 0; i--) {
      if (b[l] & (1 << i)) {
        t[pos].b[i] = b[l];
        t[pos].sz++;
        break;
      }
    }
    return;
  }
  int mid = (l + r) >> 1;
  build((pos << 1), l, mid);
  build((pos << 1 | 1), mid + 1, r);
  t[pos] = t[(pos << 1)];
  merge(t[pos], t[(pos << 1 | 1)]);
}
void modify(int pos, int l, int r, int pl) {
  if (l == r) {
    t[pos].sz = 0;
    memset(t[pos].b, 0, sizeof(t[pos].b));
    for (int i = 29; i >= 0; i--) {
      if (b[l] & (1 << i)) {
        t[pos].b[i] = b[l];
        t[pos].sz++;
        break;
      }
    }
    return;
  }
  int mid = (l + r) >> 1;
  if (pl <= mid) {
    modify((pos << 1), l, mid, pl);
  } else {
    modify((pos << 1 | 1), mid + 1, r, pl);
  }
  t[pos] = t[(pos << 1)];
  merge(t[pos], t[(pos << 1 | 1)]);
}
void ask(int pos, int l, int r, int lp, int rp) {
  if (l == lp && r == rp) {
    merge(ans, t[pos]);
    return;
  }
  int mid = (l + r) >> 1;
  if (rp <= mid) {
    ask((pos << 1), l, mid, lp, rp);
    return;
  }
  if (lp > mid) {
    ask((pos << 1 | 1), mid + 1, r, lp, rp);
    return;
  }
  ask((pos << 1), l, mid, lp, mid);
  ask((pos << 1 | 1), mid + 1, r, mid + 1, rp);
  return;
}
int main() {
  int i, j, l, r, x, opt;
  read(n);
  read(q);
  for (i = 1; i <= n; i++) {
    read(a[i]);
  }
  b[1] = a[1];
  for (i = 2; i <= n; i++) {
    b[i] = a[i - 1] ^ a[i];
  }
  for (i = 1; i <= n; i++) {
    add(i, a[i] ^ a[i - 1]);
  }
  build(1, 1, n);
  while (q--) {
    read(opt);
    if (opt == 1) {
      read(l);
      read(r);
      read(x);
      add(l, x);
      add(r + 1, x);
      b[l] ^= x;
      b[r + 1] ^= x;
      modify(1, 1, n, l);
      if (r + 1 <= n) modify(1, 1, n, r + 1);
    } else {
      read(l);
      read(r);
      ans.sz = 0;
      memset(ans.b, 0, sizeof(ans.b));
      if (l != r) ask(1, 1, n, l + 1, r);
      if (ans.sz < 30) {
        int x = ask(l);
        for (j = 29; j >= 0; j--) {
          if (x & (1 << j)) {
            if (!ans.b[j]) {
              ans.b[j] = x;
              ans.sz++;
              break;
            }
            x ^= ans.b[j];
          }
        }
      }
      write((1 << ans.sz)), *sti++ = '\n';
    }
  }
  fwrite(Buff, 1, sti - Buff, stdout);
  return 0;
}
