#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
using namespace std;
int read() {
  int sum = 0;
  char ch = getchar();
  while (ch < '0' || ch > '9') ch = getchar();
  while (ch <= '9' && ch >= '0') sum = sum * 10 + ch - '0', ch = getchar();
  return sum;
}
int n;
struct seg_tree {
  int d[200010 << 2][35];
  int st[35];
  void Insert(int id, int a) {
    for (int i = 30; i >= 0; i--)
      if (a & (1 << i)) {
        if (!d[id][i]) {
          d[id][i] = a;
          break;
        } else
          a ^= d[id][i];
      } else if (!a)
        break;
  }
  void up(int now) {
    memset(d[now], 0, sizeof(d[now]));
    for (int j = 0; j <= 30; j++)
      Insert(now, d[now << 1][j]), Insert(now, d[now << 1 | 1][j]);
  }
  void gai(int now, int k) {
    int qq = 0, tt;
    for (int j = 30; j >= 0; j--)
      if (d[now][j]) {
        qq = j;
        break;
      }
    d[now][qq] ^= k;
  }
  void modify(int now, int l, int r, int t, int k) {
    if (t > n) return;
    if (l == r) {
      gai(now, k);
      return;
    }
    int mid = l + r >> 1;
    if (t <= mid) modify(now << 1, l, mid, t, k);
    if (t >= mid + 1) modify(now << 1 | 1, mid + 1, r, t, k);
    up(now);
  }
  void query(int now, int l, int r, int ll, int rr) {
    if (ll > rr) return;
    if (ll <= l && r <= rr) {
      for (int i = 0; i <= 30; i++) Insert(0, d[now][i]);
      return;
    }
    int mid = l + r >> 1;
    if (ll <= mid) query(now << 1, l, mid, ll, rr);
    if (rr >= mid + 1) query(now << 1 | 1, mid + 1, r, ll, rr);
  }
} S;
struct seg_ttt {
  int sum[200010 << 2];
  int lz[200010 << 2];
  void gai(int now, int t) {
    sum[now] ^= t;
    lz[now] ^= t;
  }
  void pushdown(int now) {
    if (!lz[now]) return;
    gai(now << 1, lz[now]);
    gai(now << 1 | 1, lz[now]);
    lz[now] = 0;
  }
  void modify(int now, int l, int r, int ll, int rr, int kk) {
    if (ll <= l && r <= rr) {
      gai(now, kk);
      return;
    }
    pushdown(now);
    int mid = l + r >> 1;
    if (ll <= mid) modify(now << 1, l, mid, ll, rr, kk);
    if (rr >= mid + 1) modify(now << 1 | 1, mid + 1, r, ll, rr, kk);
  }
  int query(int now, int l, int r, int t) {
    if (l == r) return sum[now];
    pushdown(now);
    int mid = l + r >> 1;
    if (t <= mid) return query(now << 1, l, mid, t);
    if (t >= mid + 1) return query(now << 1 | 1, mid + 1, r, t);
  }
} T;
int q;
int w[200010], s[200010];
int main() {
  n = read(), q = read();
  for (int i = 1; i <= n; i++) {
    w[i] = read();
    S.modify(1, 1, n, i, s[i] = (w[i] ^ w[i - 1]));
    T.modify(1, 1, n, i, i, w[i]);
  }
  for (int i = 1; i <= q; i++) {
    int ty = read();
    if (ty == 1) {
      int l = read(), r = read(), k = read();
      T.modify(1, 1, n, l, r, k);
      S.modify(1, 1, n, l, k);
      S.modify(1, 1, n, r + 1, k);
    } else {
      int l = read(), r = read();
      memset(S.d[0], 0, sizeof(S.d[0]));
      S.query(1, 1, n, l + 1, r);
      S.Insert(0, T.query(1, 1, n, l));
      int tt = 0;
      for (int j = 0; j <= 30; j++)
        if (S.d[0][j]) tt++;
      cout << (1 << tt) << '\n';
    }
  }
  return 0;
}
