#include <bits/stdc++.h>
using namespace std;
int gcd(int x, int y) {
  if (y == 0) return x;
  return gcd(y, x % y);
}
int lcm(int x, int y) { return x / gcd(x, y) * y; }
int lowbit(int x) { return x & (-x); }
int quickmod(int x, int y, int mod) {
  x = x % mod;
  int ans = 1;
  while (y) {
    if (y & 1) ans = 1LL * ans * x % mod;
    y >>= 1;
    x = 1LL * x * x % mod;
  }
  return ans;
}
const int INF = 0x3f3f3f3f;
const double EPS = 1e-10;
const double PI = acos(-1.0);
const int MOD = 1e9 + 7;
const int maxn = 200005;
int n, q;
int num[maxn];
struct node {
  int lson, rson, l, r, shu, bas[30];
  void add(int x) {
    for (int i = 0; i < 30; i++) {
      if ((x >> i) & 1) {
        if (bas[i])
          x ^= bas[i];
        else {
          bas[i] = x;
          return;
        }
      }
    }
  }
  int cnt() {
    int temp = 0;
    for (int i = 0; i < 30; i++) {
      if (bas[i]) temp++;
    }
    return temp;
  }
} T[4 * maxn];
int root, cntt;
inline void pushup(int x) {
  memset(T[x].bas, 0, sizeof(T[x].bas));
  for (int i = 0; i < 30; i++)
    if (T[T[x].lson].bas[i]) T[x].add(T[T[x].lson].bas[i]);
  for (int i = 0; i < 30; i++)
    if (T[T[x].rson].bas[i]) T[x].add(T[T[x].rson].bas[i]);
}
void build(int &x, int l, int r) {
  x = ++cntt;
  T[x].l = l;
  T[x].r = r;
  memset(T[x].bas, 0, sizeof(T[x].bas));
  if (l == r) {
    T[x].shu = num[l] ^ num[l - 1];
    T[x].add(num[l] ^ num[l - 1]);
    return;
  }
  int mid = (l + r) / 2;
  build(T[x].lson, l, mid);
  build(T[x].rson, mid + 1, r);
  pushup(x);
}
void update(int x, int pos, int value) {
  if (pos > n) return;
  if (T[x].l == T[x].r) {
    memset(T[x].bas, 0, sizeof(T[x].bas));
    T[x].shu ^= value;
    T[x].add(T[x].shu);
    return;
  }
  if (pos <= T[T[x].lson].r)
    update(T[x].lson, pos, value);
  else
    update(T[x].rson, pos, value);
  pushup(x);
}
int C[maxn];
void add(int x, int value) {
  while (x <= n) {
    C[x] ^= value;
    x += lowbit(x);
  }
}
int Sum(int x) {
  int res = 0;
  while (x) {
    res ^= C[x];
    x -= lowbit(x);
  }
  return res;
}
node query(int x, int l, int r) {
  node temp;
  memset(temp.bas, 0, sizeof(temp.bas));
  if (l > r) return temp;
  if (T[x].r < l || T[x].l > r) return temp;
  if (T[x].r <= r && T[x].l >= l) return T[x];
  node temp1 = query(T[x].lson, l, r);
  node temp2 = query(T[x].rson, l, r);
  for (int i = 0; i < 30; i++)
    if (temp1.bas[i]) temp.add(temp1.bas[i]);
  for (int i = 0; i < 30; i++)
    if (temp2.bas[i]) temp.add(temp2.bas[i]);
  return temp;
}
int main() {
  scanf("%d%d", &n, &q);
  for (int i = 1; i <= n; i++) {
    scanf("%d", &num[i]);
    add(i, num[i] ^ num[i - 1]);
  }
  build(root, 1, n);
  int type;
  for (int nc = 1; nc <= q; nc++) {
    scanf("%d", &type);
    if (type == 1) {
      int v1, v2, v3;
      scanf("%d%d%d", &v1, &v2, &v3);
      update(root, v1, v3);
      update(root, v2 + 1, v3);
      add(v1, v3);
      add(v2 + 1, v3);
    } else {
      int v1, v2;
      scanf("%d%d", &v1, &v2);
      node temp = query(root, v1 + 1, v2);
      temp.add(Sum(v1));
      printf("%d\n", 1 << temp.cnt());
    }
  }
  return 0;
}
