#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=100010;
int dp[4010][4010],arr[4010],H[4010],vis[4010],n,m;
void init()
{
    memset(vis,0,sizeof vis);
    sort(H,H+m);
    m=unique(H,H+m)-H;
}
int Hash(int x)
{
    return lower_bound(H,H+m,x)-H;
}
int main()
{
    int i,j,ans;
    while(~scanf("%d",&n))
    {
        if(n==1)
        {
            scanf("%d",&arr[1]);
            printf("1\n");
            continue;
        }
        for(i=0;i<n;i++)
            scanf("%d",&arr[i]),H[i]=arr[i];
        m=n;
        init();
        for(i=0;i<n;i++)
            arr[i]=Hash(arr[i]),vis[arr[i]]++;
        ans=2;
        memset(dp,0,sizeof dp);
        for(i=n-1;i>=0;i--)
        {
            vis[arr[i]]--;
            for(j=i-1;j>=0;j--)
            {
                if(arr[i]==arr[j])
                    continue;
                if(!dp[arr[i]][arr[j]])
                    dp[arr[i]][arr[j]]=j*maxn+2;
                else if(i<dp[arr[i]][arr[j]]/maxn)
                    dp[arr[i]][arr[j]]=j*maxn+dp[arr[i]][arr[j]]+2;
                if(vis[arr[i]])
                    ans=max(ans,dp[arr[i]][arr[j]]%maxn+1);
                else
                    ans=max(ans,dp[arr[i]][arr[j]]%maxn);
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <string>
#include <algorithm>
#include <map>
#include <set>
using namespace std;

typedef long long ll;
int m[1000001];
const int size = 5;
int a[size], dp[size][size];

int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
#endif
	//memset(a, 1, sizeof(int)*size);
	int n;
	cin >> n;
	int k = 0;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
		if (m[a[i]] == 0)
			m[a[i]] = k++;
	}
	int ans = 1;
	for (int i = 1; i <= n; i++)
	{
		int c = m[a[i]];
		for (int j = 0; j < k; j++)
		{
			if (j == c) continue;
			if (dp[c][j] % 2 == 0)
				++dp[c][j];
			if (dp[j][c] % 2 == 1)
				++dp[j][c];
			ans = max(ans,max(dp[j][c],dp[c][j]));
		}
	}
	cout << ans;
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <string>
#include <algorithm>
#include <map>
#include <set>
using namespace std;

typedef long long ll;

int main()
{
#ifndef ONLINE_JUDGE
    freopen("input.txt","r",stdin);
#endif
	int n;
	cin >> n;
	map<int, vector<int> > dp;
	for (int i = 0; i < n; i++)
	{
		int c;
		cin >> c;
		dp[c].push_back(i);
	}
	int maxi = 1;
	map<int, vector<int> >::iterator it, jt;
	for (it = dp.begin(); it != dp.end(); it++)
	for (jt = dp.begin(); jt != dp.end(); jt++)
		if (it != jt)
		{
			vector<int>& a = it->second, b = jt->second;
			int c1 = it->first, c2 = jt->first;
			int k = 1, ind1 = 0, ind2 = 0, isFirst = false;
			while (true)
			{
				if (isFirst)
				{
					int pos = b[ind2];
					while (ind1 < a.size() && a[ind1] < pos) ++ind1;
					if (ind1 == a.size())
						break;
					else
						++k;
				}
				else
				{
					int pos = a[ind1];
					while (ind2 < b.size() && b[ind2] < pos) ++ind2;
					if (ind2 == b.size())
						break;
					else
						++k;
				}
				isFirst = !isFirst;
			}
			maxi = max(maxi,k);
		}
	cout << maxi;
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <string>
#include <algorithm>
#include <map>
#include <set>
using namespace std;

typedef long long ll;
int m[1000001];
const int size = 4001;
int a[size], dp[size][size];

int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
#endif
	//memset(a, 1, sizeof(int)*size);
	int n;
	cin >> n;
	int k = 0;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
		if (m[a[i]] == 0)
			m[a[i]] = k++;
	}
	int ans = 1;
	for (int i = 1; i <= n; i++)
	{
		int c = m[a[i]];
		for (int j = 0; j < k; j++)
		{
			if (j == c) continue;
			dp[c][j] = max(dp[c][j], dp[j][c] + 1);
			ans = max(ans,dp[c][j]);
		}
	}
	cout << ans;
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <string>
#include <algorithm>
#include <map>
#include <set>
using namespace std;

typedef long long ll;
int m[1000001];
const int size = 4001;
int a[size], dp[size][size];

int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
#endif
	//memset(a, 1, sizeof(int)*size);
	int n;
	cin >> n;
	int k = 0;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
		if (m[a[i]] == 0)
			m[a[i]] = k++;
	}
	int ans = 1;
	for (int i = n; i >= 1; i--)
	{
		int c = m[a[i]];
		for (int j = 0; j < k; j++)
		{
			if (j == c) continue;
			if (dp[c][j] % 2 == 0)
				++dp[c][j];
			if (dp[j][c] % 2 == 1)
				++dp[j][c];
			ans = max(ans,max(dp[j][c],dp[c][j]));
		}
	}
	cout << ans;
	return 0;
}


 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <string>
#include <algorithm>
#include <map>
#include <set>
using namespace std;

typedef long long ll;
int m[1000001];
const int size = 4001;
int a[size], dp[size][size];

int main()
{
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
#endif
    //memset(a, 1, sizeof(int)*size);
    int n;
    cin >> n;
    int k = 0;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        if (m[a[i]] == 0)
            m[a[i]] = k++;
    }
    int ans = 1;
    for (int i = 1; i <= n; i++)
    {
        int c = m[a[i]];
        for (int j = 0; j < k; j++)
        {

            if (dp[c][j] % 2 == 0)
                ++dp[c][j];
            if (dp[j][c] % 2 == 1)
                ++dp[j][c];
            ans = max(ans,max(dp[j][c],dp[c][j]));
        }
    }
    cout << ans;
    return 0;
}


#include<cstdio>
#include<cstring>
using namespace std;
const int N=200200,D=30;
int i,j,k,n,q,o,l,r,x,ch;
int a[N],b[N];
void R(int &x) {
	x=0;ch=getchar();
	while (ch<'0' || '9'<ch) ch=getchar();
	while ('0'<=ch && ch<='9') x=x*10+ch-'0',ch=getchar();
}
struct cc {
	int a[D];
	void clear() {
		memset(a,0,sizeof a);
	}
	void add(int x) {
		for (int i=D-1;i>=0;i--) if (x&1<<i) {
			if (a[i]) x^=a[i];
			else { a[i]=x;break;}
		}
	}
	int count() {
		int i,cnt=0;
		for (i=0;i<D;i++) if (a[i]) cnt++;
		return 1<<cnt;
	}
	cc operator + (const cc &n) {
		cc t;
		t=*this;
		for (int i=0;i<D;i++) if (n.a[i]) t.add(n.a[i]);
		return t;
	}
} t,T1[N<<2];
int T2[N<<2];
void T1_change(int L,int R,int x,int y,int k) {
	if (L==R) {
		T1[k].clear();
		T1[k].add(y);
		return;
	}
	int mid=(L+R)>>1;
	if (x<=mid) T1_change(L,mid,x,y,k<<1);
	else T1_change(mid+1,R,x,y,k<<1|1);
	T1[k]=T1[k<<1]+T1[k<<1|1];
}
void T2_add(int L,int R,int l,int r,int x,int k) {
	if (L==l && R==r) {
		T2[k]^=x;
		return;
	}
	int mid=(L+R)>>1;
	if (r<=mid) T2_add(L,mid,l,r,x,k<<1);
	else {
		if (l>mid) T2_add(mid+1,R,l,r,x,k<<1|1);
		else T2_add(L,mid,l,mid,x,k<<1),T2_add(mid+1,R,mid+1,r,x,k<<1|1);
	}
}
cc T1_query(int L,int R,int l,int r,int k) {
	if (l>r) return T1[0];
	if (L==l && R==r) return T1[k];
	int mid=(L+R)>>1;
	if (r<=mid) return T1_query(L,mid,l,r,k<<1);
	if (l>mid) return T1_query(mid+1,R,l,r,k<<1|1);
	return T1_query(L,mid,l,mid,k<<1)+T1_query(mid+1,R,mid+1,r,k<<1|1);
}
int T2_query(int L,int R,int x,int k) {
	if (L==R) return T2[k];
	int mid=(L+R)>>1;
	if (x<=mid) return T2[k]^T2_query(L,mid,x,k<<1);
	return T2[k]^T2_query(mid+1,R,x,k<<1|1);
}
void T1_build(int L,int R,int k) {
	if (L==R) {
		T1[k].clear();
		T1[k].add(b[L]);
		return;
	}
	int mid=(L+R)>>1;
	T1_build(L,mid,k<<1);
	T1_build(mid+1,R,k<<1|1);
	T1[k]=T1[k<<1]+T1[k<<1|1];
}
int main() {
	R(n);R(q);
	for (i=1;i<=n;i++) R(a[i]);
	for (i=1;i<=n;i++) b[i]=a[i]^a[i-1];
	T1_build(1,n,1);
	for (i=1;i<=q;i++) {
		R(o);R(l);R(r);
		if (o==1) {
			R(x);
			b[l]^=x;
			T1_change(1,n,l,b[l],1);
			b[r+1]^=x;
			if (r<n) T1_change(1,n,r+1,b[r+1],1);
			T2_add(1,n,l,r,x,1);
		}
		else {
			t=T1_query(1,n,l+1,r,1);
			t.add(T2_query(1,n,l,1)^a[l]);
			printf("%d\n",t.count());
		}
	}
}


#include<cstdio>
#include<cstring>
using namespace std;
const int N=200200,D=30;
int i,j,k,n,q,o,l,r,x,ch;
int a[N],b[N];
void R(int &x) {
	x=0;ch=getchar();
	while (ch<'0' || '9'<ch) ch=getchar();
	while ('0'<=ch && ch<='9') x=x*10+ch-'0',ch=getchar();
}
struct cc {
	int a[D];
	void clear() {
		memset(a,0,sizeof a);
	}
	void add(int x) {
		for (int i=D-1;i>=0;i--) if (x&1<<i) {
			if (a[i]) x^=a[i];
			else { a[i]=x;break;}
		}
	}
	int count() {
		int i,cnt=0;
		for (i=0;i<D;i++) if (a[i]) cnt++;
		return 1<<cnt;
	}
	cc operator + (const cc &n) {
		cc t;
		t=*this;
		for (int i=0;i<D;i++) if (n.a[i]) t.add(n.a[i]);
		return t;
	}
} t,T1[N<<2];
int T2[N<<2];
void T1_change(int L,int R,int x,int y,int k) {
	if (L==R) {
		T1[k].clear();
		T1[k].add(y);
		return;
	}
	int mid=(L+R)>>1;
	if (x<=mid) T1_change(L,mid,x,y,k<<1);
	else T1_change(mid+1,R,x,y,k<<1|1);
	T1[k]=T1[k<<1]+T1[k<<1|1];
}
void T2_add(int L,int R,int l,int r,int x,int k) {
	if (L==l && R==r) {
		T2[k]^=x;
		return;
	}
	int mid=(L+R)>>1;
	if (r<=mid) T2_add(L,mid,l,r,x,k<<1);
	else {
		if (l>mid) T2_add(mid+1,R,l,r,x,k<<1|1);
		else T2_add(L,mid,l,mid,x,k<<1),T2_add(mid+1,R,mid+1,r,x,k<<1|1);
	}
}
cc T1_query(int L,int R,int l,int r,int k) {
	if (l>r) return T1[0];
	if (L==l && R==r) return T1[k];
	int mid=(L+R)>>1;
	if (r<=mid) return T1_query(L,mid,l,r,k<<1);
	if (l>mid) return T1_query(mid+1,R,l,r,k<<1|1);
	return T1_query(L,mid,l,mid,k<<1)+T1_query(mid+1,R,mid+1,r,k<<1|1);
}
int T2_query(int L,int R,int x,int k) {
	if (L==R) return T2[k];
	int mid=(L+R)>>1;
	if (x<=mid) return T2[k]^T2_query(L,mid,x,k<<1);
	return T2[k]^T2_query(mid+1,R,x,k<<1|1);
}
void T1_build(int L,int R,int k) {
	if (L==R) {
		T1[k].clear();
		T1[k].add(b[L]);
		return;
	}
	int mid=(L+R)>>1;
	T1_build(L,mid,k<<1);
	T1_build(mid+1,R,k<<1|1);
	T1[k]=T1[k<<1]+T1[k<<1|1];
}
int main() {
	R(n);R(q);
	for (i=1;i<=n;i++) R(a[i]);
	for (i=1;i<=n;i++) b[i]=a[i]^a[i-1];
	T1_build(1,n,1);
	for (i=1;i<=q;i++) {
		R(o);R(l);R(r);
		if (o==1) {
			R(x);
			b[l]^=x;
			T1_change(1,n,l,b[l],1);
			b[r+1]^=x;
			if (r<n) T1_change(1,n,r+1,x,1);
			T2_add(1,n,l,r,x,1);
		}
		else {
			t=T1_query(1,n,l+1,r,1);
			t.add(T2_query(1,n,l,1)^a[l]);
			printf("%d\n",t.count());
		}
	}
}


// Author: 23forever
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <vector>
#include <queue>
typedef long long LL;
const int MAXN = 200000;
const int MAXL = 30;
using namespace std;

inline void enableFileIO() {
  freopen("test.in", "r", stdin);
  freopen("test.out", "w", stdout);
}

inline int read() {
  int x = 0, w = 1;
  char c = ' ';

  while (c < '0' || c > '9') {
    c = getchar();
    if (c == '-') w = -1;
  }
  while (c >= '0' && c <= '9') {
    x = (x << 1) + (x << 3) + (c ^ 48);
    c = getchar();
  }

  return x * w;
}

struct LinearBasis {
  int b[MAXL + 5], v;

  void init() {
    memset(b, 0, sizeof(b));
    v = 0;
  }

  void insert(int x) {
    for (int i = MAXL; i >= 0; --i) {
      if (x & (1 << i)) {
        if (!b[i]) {
          b[i] = x;
          return;
        } else {
          x ^= b[i];
        }
      }
    }
  }

  int count() {
    int ret = 1;
    for (int i = 0; i <= MAXL; ++i) {
      if (b[i]) ret <<= 1;
    }
    return ret;
  }
}ans;

LinearBasis merge(const LinearBasis &A, const LinearBasis &B) {
  LinearBasis ret;
  ret.init();

  for (int i = 0; i <= MAXL; ++i) {
    ret.insert(A.b[i]);
    ret.insert(B.b[i]);
  }
  ret.insert(A.v ^ B.v);
  ret.v = B.v;
  return ret;
}

int a[MAXN + 5];

struct SegmentTree {
  struct Node {
    int delta;
    LinearBasis b;
  }s[MAXN * 4 + 5];

  #define lson p << 1
  #define rson p << 1 | 1

  SegmentTree() {}

  void upd(int p) {
    s[p].b = merge(s[lson].b, s[rson].b);
  }
  void pd(int p) {
    if (s[p].delta) {
      s[lson].delta ^= s[p].delta;
      s[rson].delta ^= s[p].delta;
      s[lson].b.v ^= s[p].delta;
      s[rson].b.v ^= s[p].delta;
      s[p].delta = 0;
    }
  }

  void build(int p, int l, int r) {
    if (l == r) {
      s[p].b.v = a[l];
      return;
    }

    int mid = (l + r) >> 1;
    build(lson, l, mid);
    build(rson, mid + 1, r);
    upd(p);
  }

  void update(int p, int l, int r, int x, int y, int v) {
    if (x <= l && y >= r) {
      s[p].delta ^= v;
      s[p].b.v ^= v;
      return;
    }

    pd(p);
    int mid = (l + r) >> 1;
    if (x <= mid) update(lson, l, mid, x, y, v);
    if (y > mid) update(rson, mid + 1, r, x, y, v);
    upd(p);
  }
  void query(int p, int l, int r, int x, int y) {
    if (x <= l && y >= r) {
      ans = merge(ans, s[p].b);
      return;
    }

    pd(p);
    int mid = (l + r) >> 1;
    if (x <= mid) query(lson, l, mid, x, y);
    if (y > mid) query(rson, mid + 1, r, x, y);
    upd(p);
  }
}S;

int n, m;

void init() {
//  enableFileIO();

  n = read();
  m = read();
  for (int i = 1; i <= n; ++i) a[i] = read();
}

int main() {
  init();

  S.build(1, 1, n);
  while (m--) {
    int opt = read(), l = read(), r = read();
    switch(opt) {
      case 1: {
        int v = read();
        S.update(1, 1, n, l, r, v);
        break;
      }
      case 2: {
        ans.init();
        S.query(1, 1, n, l, r);
        printf("%d\n", ans.count());
        break;
      }
    }
  }

  return 0;
}


#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<string>
#include<stdio.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int maxn = 101111;
struct node{
    int a[33];
    int x,t;
    node(){
        x = 0;
        t = 0;
    }
}seg[maxn<<2],tmp;

int n,q;
int a[maxn];

node Merge(node l,node r){
    node ret;
    for (int _ = 0; _ < 2; _++){
        for (int i = 0; i < l.t; i++){
            int val = l.a[i];
            for (int j = 0; j < ret.t; j++){
                if (val & ret.a[j] & -ret.a[j])
                    val ^= ret.a[j];
            }
            if (val)
                ret.a[ret.t++]=val;
        }
        swap(l, r);
    }
    return ret;
}

void PushDown(int rt){
    if (!seg[rt].x) return;
    int nw = rt<<1;
    for (int _ = 0; _ < 2; _++){
        seg[nw].x ^= seg[rt].x;
        for (int i = 0; i < seg[nw].t; i++){
            if (seg[nw].a[i] & 1)
                seg[nw].a[i] ^= seg[rt].x;
        }
        nw |= 1;
    }
    seg[rt].x = 0;
}

void Update(int L,int R,int p,int l,int r,int rt){
    if (L <= l && r <= R){
        seg[rt].x ^= p;
        for (int i = 0; i < seg[rt].t; i++){
            if (seg[rt].a[i] & 1)
                seg[rt].a[i] ^= p;
        }
        return;
    }
    int m = (l + r) >> 1;
    PushDown(rt);
    if (L <= m) Update(L,R,p,lson);
    if (R > m) Update(L,R,p,rson);
    seg[rt] = Merge(seg[rt<<1], seg[rt<<1|1]);
}

node Query(int L,int R,int l,int r,int rt){
    if (L <= l && r <= R)
        return seg[rt];
    PushDown(rt);
    int m = (l + r) >> 1;
    node ret;
    if (L <= m) ret = Merge(ret, Query(L,R,lson));
    if (R > m) ret = Merge(ret, Query(L,R,rson));
    return ret;
}

void Build(int l,int r,int rt){
    if (l==r){
        seg[rt].a[0]=a[l];
        seg[rt].t=1;
        return;
    }
    int m=(l+r)>>1;
    Build(lson);
    Build(rson);
    seg[rt]=Merge(seg[rt<<1], seg[rt<<1|1]);
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n>>q;
    for (int i=1;i<=n;i++){
        //scanf("%d",a+i);
        cin>>a[i];
        a[i]=a[i]*2+1;
    }
    Build(1,n,1);
    while (q--){
        int t;
        int l,r,val;
        cin>>t;
        if (t==1){
            cin>>l>>r>>val;
            Update(l,r,val*2,1,n,1);
        }
        else{
            cin>>l>>r;
            node ans=Query(l,r,1,n,1);
            for (int i=0;i<ans.t;i++)
                if (ans.a[i] & 1)
                    ans.a[i]--;
            cout<<(1<<Merge(ans,tmp).t)<<"\n";
        }
    }
    return 0;
}


#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<string>
#include<stdio.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int maxn = 201111;
struct node{
    int a[33];
    int x,t;
    node(){
        x = 0;
        t = 0;
    }
}seg[maxn<<2],tmp;

int n,q;
int a[maxn];

node Merge(node l,node r){
    node ret;
    for (int _ = 0; _ < 2; _++){
        for (int i = 0; i < l.t; i++){
            int val = l.a[i];
            for (int j = 0; j < ret.t; j++){
                if (val & ret.a[j] & -ret.a[j])
                    val ^= ret.a[j];
            }
            if (val)
                ret.a[ret.t++]=val;
        }
        swap(l, r);
    }
    return ret;
}

void PushDown(int rt){
    if (!seg[rt].x) return;
    int nw = rt<<1;
    for (int _ = 0; _ < 2; _++){
        seg[nw].x ^= seg[rt].x;
        for (int i = 0; i < seg[nw].t; i++){
            if (seg[nw].a[i] & 1)
                seg[nw].a[i] ^= seg[rt].x;
        }
        nw |= 1;
    }
    seg[rt].x = 0;
}

void Update(int L,int R,int p,int l,int r,int rt){
    if (L <= l && r <= R){
        seg[rt].x ^= p;
        for (int i = 0; i < seg[rt].t; i++){
            if (seg[rt].a[i] & 1)
                seg[rt].a[i] ^= p;
        }
        return;
    }
    int m = (l + r) >> 1;
    PushDown(rt);
    if (L <= m) Update(L,R,p,lson);
    if (R > m) Update(L,R,p,rson);
    seg[rt] = Merge(seg[rt<<1], seg[rt<<1|1]);
}

node Query(int L,int R,int l,int r,int rt){
    if (L <= l && r <= R)
        return seg[rt];
    PushDown(rt);
    int m = (l + r) >> 1;
    node ret;
    if (L <= m) ret = Merge(ret, Query(L,R,lson));
    if (R > m) ret = Merge(ret, Query(L,R,rson));
    return ret;
}

void Build(int l,int r,int rt){
    if (l==r){
        seg[rt].a[0]=a[l];
        seg[rt].t=1;
        return;
    }
    int m=(l+r)>>1;
    Build(lson);
    Build(rson);
    seg[rt]=Merge(seg[rt<<1], seg[rt<<1|1]);
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n>>q;
    for (int i=1;i<=n;i++){
        //scanf("%d",a+i);
        cin>>a[i];
        a[i]=a[i]*2+1;
    }
    Build(1,n,1);
    while (q--){
        int t;
        int l,r,val;
        cin>>t;
        if (t==1){
            cin>>l>>r>>val;
            Update(l,r,val*2,1,n,1);
        }
        else{
            cin>>l>>r;
            node ans=Query(l,r,1,n,1);
            for (int i=0;i<ans.t;i++)
                if (ans.a[i] & 1)
                    ans.a[i]--;
            cout<<(1<<Merge(ans,tmp).t)<<"\n";
        }
    }
    return 0;
}


#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<string>
#include<stdio.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int maxn = 101111;
struct node{
    int a[33];
    int x,t;
    node(){
        x = 0;
        t = 0;
    }
}seg[maxn<<2],tmp;

int n,q;
int a[maxn];

node Merge(node l,node r){
    node ret;
    for (int _ = 0; _ < 2; _++){
        for (int i = 0; i < l.t; i++){
            int val = l.a[i];
            for (int j = 0; j < ret.t; j++){
                if (val & ret.a[j] & -ret.a[j])
                    val ^= ret.a[j];
            }
            if (val)
                ret.a[ret.t++]=val;
        }
        swap(l, r);
    }
    return ret;
}

void PushDown(int rt){
    if (!seg[rt].x) return;
    int nw = rt<<1;
    for (int _ = 0; _ < 2; _++){
        seg[nw].x ^= seg[rt].x;
        for (int i = 0; i < seg[nw].t; i++){
            if (seg[nw].a[i] & 1)
                seg[nw].a[i] ^= seg[rt].x;
        }
        nw |= 1;
    }
    seg[nw].x = 0;
}

void Update(int L,int R,int p,int l,int r,int rt){
    if (L <= l && r <= R){
        seg[rt].x ^= p;
        for (int i = 0; i < seg[rt].t; i++){
            if (seg[rt].a[i] & 1)
                seg[rt].a[i] ^= p;
        }
        return;
    }
    int m = (l + r) >> 1;
    PushDown(rt);
    if (L <= m) Update(L,R,p,lson);
    if (R > m) Update(L,R,p,rson);
    seg[rt] = Merge(seg[rt<<1], seg[rt<<1|1]);
}

node Query(int L,int R,int l,int r,int rt){
    if (L <= l && r <= R)
        return seg[rt];
    PushDown(rt);
    int m = (l + r) >> 1;
    node ret;
    if (L <= m) ret = Merge(ret, Query(L,R,lson));
    if (R > m) ret = Merge(ret, Query(L,R,rson));
    return ret;
}

void Build(int l,int r,int rt){
    if (l==r){
        seg[rt].a[0]=a[l];
        seg[rt].t=1;
        return;
    }
    int m=(l+r)>>1;
    Build(lson);
    Build(rson);
    seg[rt]=Merge(seg[rt<<1], seg[rt<<1|1]);
}

int main(){
    ios::sync_with_stdio(false);
	cin.tie(0);
    cin>>n>>q;
    for (int i=1;i<=n;i++){
        //scanf("%d",a+i);
        cin>>a[i];
        a[i]=a[i]*2+1;
    }
    Build(1,n,1);
    while (q--){
        int t;
        int l,r,val;
        cin>>t;
        if (t==1){
            cin>>l>>r>>val;
            Update(l,r,val*2,1,n,1);
        }
        else{
            cin>>l>>r;
            node ans=Query(l,r,1,n,1);
            for (int i=0;i<ans.t;i++)
                if (ans.a[i] & 1)
                    ans.a[i]--;
            cout<<(1<<Merge(ans,tmp).t)<<"\n";
        }
    }
    return 0;
}


#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<vector>
#include<numeric>
#include<map>
#include<set>
#include<cstdlib>
#include<string>
#include<cassert>
#include<iostream>
using namespace std;
typedef vector<int> vi;
typedef long long int64;
#define FOR(i,n)for(int i=0;i<(int)(n);i++)
const int MAX=210000;
int n,q,a[MAX];
const int POWER=1<<18;
struct tab {
  int len,t[31],add;
} s[2*POWER];
int len,t[64];
void gauss(const tab &a,const tab &b,tab &c){
  len=0;
  for(int i=0;i<a.len;i++){
    t[len++]=a.t[i];
  }
  for(int i=0;i<b.len;i++){
    t[len++]=b.t[i];
  }
  int next=0;
  for(int i=0;i<=30;i++){
    int j=next;
    while(j<len&&!(t[j]&1<<i)){
      ++j;
    }
    if(j==len)continue;
    swap(t[next],t[j]);
    for(j=0;j<len;j++)if(j!=next&&(t[j]&1<<i)){
      t[j]^=t[next];
    }
    ++next;
  }
  c.len=next;
  for(int i=0;i<next;i++){
    c.t[i]=t[i];
  }
}
void fix(tab &a,int add){
  for(int i=0;i<a.len;i++)if(a.t[i]>>30){
    a.t[i]^=add;
  }
}
void recalc(int pos){
  if(pos>=POWER){
    return;
  }
  gauss(s[2*pos],s[2*pos+1],s[pos]);
  fix(s[pos],s[pos].add);
}
int main(){
  scanf("%d %d",&n,&q);
  for(int i=0;i<n;i++){
    scanf("%d",&a[i]);
    s[POWER+i].len=1;
    s[POWER+i].t[0]=a[i]|1<<30;
  }
  for(int i=POWER-1;i;i--){
    gauss(s[2*i],s[2*i+1],s[i]);
  }
  while(q--){
    int type,from,to,k;
    scanf("%d %d %d",&type,&from,&to);
    --from;--to;
    if(type==1){
      scanf("%d",&k);
      from+=POWER;
      s[from].t[0]^=k;
      to+=POWER;
      if(from<to){
        s[to].t[0]^=k;
      }
      while(from+1<to){
        recalc(from);
        recalc(to);
        if(from%2==0){
          s[from+1].add^=k;
          fix(s[from+1],k);
        }
        if(to%2){
          s[to-1].add^=k;
          fix(s[to-1],k);
        }
        from/=2;
        to/=2;
      }
      while(from){
        recalc(from);
        from/=2;
      }
      while(to){
        recalc(to);
        to/=2;
      }
    }else if(type==2){
      from+=POWER;
      tab left=s[from];
      to+=POWER;
      tab right=s[to];
      while(from+1<to){
        if(from%2==0){
          gauss(left,s[from+1],left);
        }
        if(to%2){
          gauss(right,s[to-1],right);
        }
        from/=2;
        to/=2;
        fix(left,s[from].add);
        fix(right,s[to].add);
      }
      while(from/=2){
        fix(left,s[from].add);
      }
      while(to/=2){
        fix(right,s[to].add);
      }
      tab result;
      for(int i=0;i<left.len;i++){
        left.t[i]&=~(1<<30);
      }
      for(int i=0;i<right.len;i++){
        right.t[i]&=~(1<<30);
      }
      gauss(left,right,result);
      printf("%d\n",1<<result.len);
    }
  }
  return 0;
}


#include<stdio.h>
#include<iostream>
#define lc k<<1
#define rc k<<1|1
using namespace std;
namespace INPUT{
	const int L=1<<20;
	char _buf[L],*S,*T,c;
	char _gc(){
		if(S==T){
			T=(S=_buf)+fread(_buf,1,L,stdin);
			if(S==T) return EOF;
		}return *S++;
	}
	void Readi(int &x){
		for(c=_gc();c<'0'||c>'9';c=_gc());
		for(x=0;c>='0'&&c<='9';c=_gc())x=(x<<3)+(x<<1)+(c&15);
	}
}
using INPUT::Readi;
const int N=200010,S=30;
struct basis{
	int v[S+1];
	void Insert(int val){
		for(int i=S;i>=0;i--)
			if((val>>i)&1)
				if(v[i])val^=v[i];
				else{v[i]=val;break;}
	}
	int Count(){
		int s=0;
		for(int i=0;i<=S;i++)s+=v[i]>0;
		return 1<<s;
	}
}T[N*4];
basis merge(basis a,basis b){
	for(int i=0;i<=S;i++)a.Insert(b.v[i]);
	return a;
}
int n,q,a[N],s[N];
inline int lowbit(int x){return x&-x;}
void upd(int x,int v){
	for(;x<=n;x+=lowbit(x))
		s[x]^=v;
}
int que(int x){
	int res=0;
	for(;x>0;x-=lowbit(x))res^=s[x];
	return res;
}
void build(int k,int l,int r){
	if(l==r){T[k].Insert(a[l]);return;}
	int mid=l+r>>1;
	build(lc,l,mid);build(rc,mid+1,r);
	T[k]=merge(T[lc],T[rc]);
}
basis query(int k,int L,int R,int l,int r){
	if(l<=L&&R<=r)return T[k];
	int mid=L+R>>1;
	if(r<=mid)return query(lc,L,mid,l,r);
	if(l>mid)return query(rc,mid+1,R,l,r);
	return merge(query(lc,L,mid,l,mid),query(rc,mid+1,R,mid+1,r));
}
void update(int k,int l,int r,int pos,int v){
	if(l==r){
		for(int i=0;i<=S;i++)T[k].v[i]=0;
		T[k].Insert(v);return;
	}
	int mid=l+r>>1;
	if(pos<=mid)update(lc,l,mid,pos,v);
	else update(rc,mid+1,r,pos,v);
	T[k]=merge(T[lc],T[rc]);
}
int main(){
	Readi(n);Readi(q);
	for(int i=1;i<=n;i++)Readi(a[i]);
	for(int i=n;i>=1;i--)a[i]=a[i]^a[i-1],upd(i,a[i]);
	build(1,1,n);int op,l,r,x;
	while(q--){
		Readi(op);Readi(l);Readi(r);
		if(op==1){
			Readi(x);
			update(1,1,n,l,a[l]^=x);
			if(r<n)update(1,1,n,r+1,a[r+1]^=x);
			upd(l,x);upd(r+1,x);
		}
		else{
			basis Ans;for(int i=0;i<=S;i++)Ans.v[i]=0;
			if(l<r)Ans=query(1,1,n,l+1,r);
			Ans.Insert(que(l));
			printf("%d\n",Ans.Count());
		}
	}
	return 0;
}


#include<stdio.h>
#include<iostream>
#define lc k<<1
#define rc k<<1|1
using namespace std;
namespace INPUT{
	const int L=1<<20;
	char _buf[L],*S,*T,c;
	char _gc(){
		if(S==T){
			T=(S=_buf)+fread(_buf,1,L,stdin);
			if(S==T) return EOF;
		}return *S++;
	}
	void Readi(int &x){
		for(c=_gc();c<'0'||c>'9';c=_gc());
		for(x=0;c>='0'&&c<='9';c=_gc())x=(x<<3)+(x<<1)+(c&15);
	}
}
using INPUT::Readi;
const int N=200010,S=20;
struct basis{
	int v[S+1];
	void Insert(int val){
		for(int i=S;i>=0;i--)
			if((val>>i)&1)
				if(v[i])val^=v[i];
				else{v[i]=val;break;}
	}
	int Count(){
		int s=0;
		for(int i=0;i<=S;i++)s+=v[i]>0;
		return 1<<s;
	}
}T[N*4];
basis merge(basis a,basis b){
	for(int i=0;i<=S;i++)a.Insert(b.v[i]);
	return a;
}
int n,q,a[N],s[N];
inline int lowbit(int x){return x&-x;}
void upd(int x,int v){
	for(;x<=n;x+=lowbit(x))
		s[x]^=v;
}
int que(int x){
	int res=0;
	for(;x>0;x-=lowbit(x))res^=s[x];
	return res;
}
void build(int k,int l,int r){
	if(l==r){T[k].Insert(a[l]);return;}
	int mid=l+r>>1;
	build(lc,l,mid);build(rc,mid+1,r);
	T[k]=merge(T[lc],T[rc]);
}
basis query(int k,int L,int R,int l,int r){
	if(l<=L&&R<=r)return T[k];
	int mid=L+R>>1;
	if(r<=mid)return query(lc,L,mid,l,r);
	if(l>mid)return query(rc,mid+1,R,l,r);
	return merge(query(lc,L,mid,l,mid),query(rc,mid+1,R,mid+1,r));
}
void update(int k,int l,int r,int pos,int v){
	if(l==r){
		for(int i=0;i<=S;i++)T[k].v[i]=0;
		T[k].Insert(v);return;
	}
	int mid=l+r>>1;
	if(pos<=mid)update(lc,l,mid,pos,v);
	else update(rc,mid+1,r,pos,v);
	T[k]=merge(T[lc],T[rc]);
}
int main(){
	Readi(n);Readi(q);
	for(int i=1;i<=n;i++)Readi(a[i]);
	for(int i=n;i>=1;i--)a[i]=a[i]^a[i-1],upd(i,a[i]);
	build(1,1,n);int op,l,r,x;
	while(q--){
		Readi(op);Readi(l);Readi(r);
		if(op==1){
			Readi(x);
			update(1,1,n,l,a[l]^=x);
			if(r<n)update(1,1,n,r+1,a[r+1]^=x);
			upd(l,x);upd(r+1,x);
		}
		else{
			basis Ans;for(int i=0;i<=S;i++)Ans.v[i]=0;
			if(l<r)Ans=query(1,1,n,l+1,r);
			Ans.Insert(que(l));
			printf("%d\n",Ans.Count());
		}
	}
	return 0;
}


#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct node
{
	int q[65];
	int cnt;
}tree[810000];
int tree1[810000];
int a[210000],b[210000];
int n,q;
int t1,t2,t3,t4;
node gas(node &x)
{
	for(int i=0;i<=30;i++)
	{
		int w=0;
		for(int j=i+1;j<=x.cnt;j++)
		if(x.q[j]&(1<<i))
		{
			w=j;
			break;
		}
		if(w)
		{
			for(int j=1;j<=x.cnt;j++)
			if(j!=w&&x.q[j]&(1<<i))
			{
				x.q[j]^=x.q[w];
			}
			swap(x.q[w],x.q[i+1]);
		}
	}
	node ans;
	memset(&ans,0,sizeof(ans));
	for(int i=1;i<=x.cnt;i++)
	{
		if(x.q[i])
		ans.q[++ans.cnt]=x.q[i];
	}
	return ans;
}
node cal(node &x,node &y)
{
	node ans;
	memset(&ans,0,sizeof(ans));
	for(int i=1;i<=x.cnt;i++)
	{
		ans.q[++ans.cnt]=x.q[i];
	}
	for(int i=1;i<=y.cnt;i++)
	{
		ans.q[++ans.cnt]=y.q[i];
	}
	return gas(ans);
}
void build(int l,int r,int now)
{
	if(l==r)
	{
		tree[now].cnt=1;
		tree[now].q[1]=b[l];
		return;
	}
	int mid=(l+r)>>1;
	build(l,mid,now*2);
	build(mid+1,r,now*2+1);
	tree[now]=cal(tree[now*2],tree[now*2+1]);
}
void insert(int l,int r,int now,int pos,int val)
{
	if(l==r)
	{
		tree[now].q[1]^=val;
		b[l]^=val;
		return;
	}
	int mid=(l+r)>>1;
	if(pos<=mid)
	insert(l,mid,now*2,pos,val);
	else
	insert(mid+1,r,now*2+1,pos,val);
	tree[now]=cal(tree[now*2],tree[now*2+1]);
}
void insert1(int l,int r,int now,int lq,int rq,int val)
{
	if(lq<=l&&r<=rq)
	{
		if(l!=r)
		tree1[now]^=val;
		else
		a[l]^=val;
		return;
	}
	int mid=(l+r)>>1;
	if(mid>=lq)
	insert1(l,mid,now*2,lq,rq,val);
	if(mid<rq)
	insert1(mid+1,r,now*2+1,lq,rq,val);
}
node query(int l,int r,int now,int lq,int rq)
{
	if(lq<=l&&r<=rq)
	{
		return tree[now];
	}
	int mid=(l+r)>>1;
	node a1,a2;
	memset(&a1,0,sizeof(a1));
	memset(&a2,0,sizeof(a2));
	if(mid>=lq)
	a1=query(l,mid,now*2,lq,rq);
	if(mid<rq)
	a2=query(mid+1,r,now*2+1,lq,rq);
	return cal(a1,a2);
}
void pushdown(int now,int l,int r)
{
	if(tree1[now])
	{
		int mid=(l+r)>>1;
		if(mid!=l)
		tree1[now*2]^=tree1[now];
		else
		a[l]^=tree1[now];
		if(mid+1!=r)
		tree1[now*2+1]^=tree1[now];
		else
		a[r]^=tree1[now];
	}
	tree1[now]=0;
}
void query1(int l,int r,int now,int pos)
{
	if(l==r)
	return;
	int mid=(l+r)>>1;
	pushdown(now,l,r);
	if(pos<=mid)
	query1(l,mid,now*2,pos);
	else
	query1(mid+1,r,now*2+1,pos);
}
int main()
{
	//freopen("1.in","r",stdin);
	scanf("%d%d",&n,&q);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
	}
	b[1]=a[1];
	for(int i=2;i<=n;i++)
	{
		b[i]=a[i-1]^a[i];
	}
	build(1,n,1);
	for(int i=1;i<=q;i++)
	{
		scanf("%d",&t1);
		if(t1==1)
		{
			scanf("%d%d%d",&t2,&t3,&t4);
			insert(1,n,1,t2,t4);
			if(t3!=n)
			insert(1,n,1,t3+1,t4);
			insert1(1,n,1,t2,t3,t4);
		}
		else
		{
			scanf("%d%d",&t2,&t3);
			node a1,a2;
			memset(&a1,0,sizeof(a1));
			if(t2!=t3)
			a1=query(1,n,1,t2+1,t3);
			query1(1,n,1,t2);
			a2.cnt=1;
			a2.q[1]=a[t2];
			a1=cal(a1,a2);
			printf("%d\n",1<<a1.cnt);
		}
	}
	return 0;
}


#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct node
{
	int q[65];
	int cnt;
}tree[810000];
int tree1[810000];
int a[210000],b[210000];
int n,q;
int t1,t2,t3,t4;
node gas(node &x)
{
	bool used[65];
	memset(used,0,sizeof(used));
	for(int i=0;i<=30;i++)
	{
		int w=0;
		for(int j=1;j<=x.cnt;j++)
		if(!used[j]&&x.q[j]&(1<<i))
		{
			w=j;
			break;
		}
		if(w)
		{
			for(int j=1;j<=x.cnt;j++)
			if(j!=w&&x.q[j]&(1<<i))
			{
				x.q[j]^=x.q[w];
			}
			used[w]=1;
		}
	}
	node ans;
	memset(&ans,0,sizeof(ans));
	for(int i=1;i<=x.cnt;i++)
	{
		if(x.q[i])
		ans.q[++ans.cnt]=x.q[i];
	}
	return ans;
}
node cal(node &x,node &y)
{
	node ans;
	memset(&ans,0,sizeof(ans));
	for(int i=1;i<=x.cnt;i++)
	{
		ans.q[++ans.cnt]=x.q[i];
	}
	for(int i=1;i<=y.cnt;i++)
	{
		ans.q[++ans.cnt]=y.q[i];
	}
	return gas(ans);
}
void build(int l,int r,int now)
{
	if(l==r)
	{
		tree[now].cnt=1;
		tree[now].q[1]=b[l];
		return;
	}
	int mid=(l+r)>>1;
	build(l,mid,now*2);
	build(mid+1,r,now*2+1);
	tree[now]=cal(tree[now*2],tree[now*2+1]);
}
void insert(int l,int r,int now,int pos,int val)
{
	if(l==r)
	{
		tree[now].q[1]^=val;
		b[l]^=val;
		return;
	}
	int mid=(l+r)>>1;
	if(pos<=mid)
	insert(l,mid,now*2,pos,val);
	else
	insert(mid+1,r,now*2+1,pos,val);
	tree[now]=cal(tree[now*2],tree[now*2+1]);
}
void insert1(int l,int r,int now,int lq,int rq,int val)
{
	if(lq<=l&&r<=rq)
	{
		if(l!=r)
		tree1[now]^=val;
		else
		a[l]^=val;
		return;
	}
	int mid=(l+r)>>1;
	if(mid>=lq)
	insert1(l,mid,now*2,lq,rq,val);
	if(mid<rq)
	insert1(mid+1,r,now*2+1,lq,rq,val);
}
node query(int l,int r,int now,int lq,int rq)
{
	if(lq<=l&&r<=rq)
	{
		return tree[now];
	}
	int mid=(l+r)>>1;
	node a1,a2;
	memset(&a1,0,sizeof(a1));
	memset(&a2,0,sizeof(a2));
	if(mid>=lq)
	a1=query(l,mid,now*2,lq,rq);
	if(mid<rq)
	a2=query(mid+1,r,now*2+1,lq,rq);
	return cal(a1,a2);
}
void pushdown(int now,int l,int r)
{
	if(tree1[now])
	{
		int mid=(l+r)>>1;
		if(mid!=l)
		tree1[now*2]^=tree1[now];
		else
		a[l]^=tree1[now];
		if(mid+1!=r)
		tree1[now*2+1]^=tree1[now];
		else
		a[r]^=tree1[now];
	}
	tree1[now]=0;
}
void query1(int l,int r,int now,int pos)
{
	if(l==r)
	return;
	int mid=(l+r)>>1;
	pushdown(now,l,r);
	if(pos<=mid)
	query1(l,mid,now*2,pos);
	else
	query1(mid+1,r,now*2+1,pos);
}
int main()
{
	//freopen("1.in","r",stdin);
	scanf("%d%d",&n,&q);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
	}
	b[1]=a[1];
	for(int i=2;i<=n;i++)
	{
		b[i]=a[i-1]^a[i];
	}
	build(1,n,1);
	for(int i=1;i<=q;i++)
	{
		scanf("%d",&t1);
		if(t1==1)
		{
			scanf("%d%d%d",&t2,&t3,&t4);
			insert(1,n,1,t2,t4);
			if(t3!=n)
			insert(1,n,1,t3+1,t4);
			insert1(1,n,1,t2,t3,t4);
		}
		else
		{
			scanf("%d%d",&t2,&t3);
			node a1,a2;
			memset(&a1,0,sizeof(a1));
			if(t2!=t3)
			a1=query(1,n,1,t2+1,t3);
			query1(1,n,1,t2);
			a2.cnt=1;
			a2.q[1]=a[t2];
			a1=cal(a1,a2);
			printf("%d\n",1<<a1.cnt);
		}
	}
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pi;
const double PI=acos(-1);
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define rep(i,a,b) for (int i=(a);i<=(b);i++)
#define per(i,a,b) for (int i=(a);i>=(b);i--)
#define Rep(i,a,b) for (int i=(a);i<(b);i++)
#define Per(i,a,b) for (int i=(a);i>(b);i--)
#define travel_set(it,a) for (set<int>::iterator (it)=(a).begin();(it)!=(a).end();(it)++)
#define travel_map(it,a) for (map<int>::iterator (it)=(a).begin();(it)!=(a).end();(it)++)
#define travel_vec(it,a) for (vector<int>::iterator (it)=(a).begin();(it)!=(a).end();(it)++)
#define p(x) cout << x << endl;
#define def cout << "find" << endl;
#define what_is(x) cout << #x << " is " << x << endl;
template <class T>T sqr(T x){return x*x;}
template <class T>T alex(T x){return (x>0)?x:-x;}
template <class T>void read(T&x){
	x=0;T f=1;char ch=getchar();
	while ((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
	if (ch=='-')f=-1,ch=getchar();
	while (ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
	x*=f;
}

//---------------------------------------------------head---------------------------------------------------

#define maxl 32
#define maxn 200005
int n,q;int a[maxn];
int b[maxn];
struct Node{
	int f[maxl];Node(){}
	void clear(){memset(f,0,sizeof(f));}
	void insert(int x){
		// printf("%d\n", x);
		per(i,31,0)if ((x>>i)&1){
			if (!f[i]){f[i]=x;break;}
			else x^=f[i];
		}
	}
	int count(){
		int res=0;
		rep(i,0,31)if (f[i])res++;
		return res;
	}
	void print(){
		rep(i,0,31)if (f[i])printf("(%d %d) ",i,f[i]);printf("\n");
	}
};
struct Tree{
	int l,r,ans,lzy;Node res;
}T[maxn<<2];
Node merge(Node x,Node y){
	Node res;res.clear();res=x;
	Rep(i,0,32)if (y.f[i])res.insert(y.f[i]);
	return res;
}
void update(int rot){
	T[rot].ans=T[rot<<1].ans^T[rot<<1|1].ans;
	T[rot].res=merge(T[rot<<1].res,T[rot<<1|1].res);
}
void pushdown(int rot){
	if (T[rot].lzy){
		T[rot<<1].ans^=T[rot].lzy;T[rot<<1|1].ans^=T[rot].lzy;
		T[rot<<1].lzy^=T[rot].lzy;T[rot<<1|1].lzy^=T[rot].lzy;
		T[rot].lzy=0;
	}
}
void build(int rot,int l,int r){
	// printf("%d %d %d %d %d\n",a[1],a[2],a[3],a[4],a[5]);
	T[rot].l=l;T[rot].r=r;if (l==r){T[rot].res.insert(a[l]);T[rot].ans=b[l];return;}int mid=(l+r)>>1;
	build(rot<<1,l,mid);build(rot<<1|1,mid+1,r);update(rot);
	// printf("%d %d:",l,r);T[rot].res.print();
}
void change(int rot,int pos,int x){
	if (T[rot].l==T[rot].r){
		T[rot].res.clear();a[pos]^=x;
		// printf("change %d %d %d\n",pos,a[pos],x);
		T[rot].res.insert(a[pos]);
		return;
	}
	pushdown(rot);
	int mid=(T[rot].l+T[rot].r)>>1;
	if (pos<=mid)change(rot<<1,pos,x);else change(rot<<1|1,pos,x);
	update(rot);
}
void changexor(int rot,int l,int r,int v){
	if (T[rot].l==l&&T[rot].r==r){
		T[rot].ans^=v;T[rot].lzy^=v;return;
	}
	pushdown(rot);int mid=(T[rot].l+T[rot].r)>>1;
	if (r<=mid)changexor(rot<<1,l,r,v);else if (l>mid)changexor(rot<<1|1,l,r,v);
	else changexor(rot<<1,l,mid,v),changexor(rot<<1|1,mid+1,r,v);update(rot);
}
Node query(int rot,int l,int r){
	if (T[rot].l==l&&T[rot].r==r){
		return T[rot].res;
	}pushdown(rot);int mid=(T[rot].l+T[rot].r)>>1;
	if (r<=mid)return query(rot<<1,l,r);else if (l>mid)return query(rot<<1|1,l,r);
	else return merge(query(rot<<1,l,mid),query(rot<<1|1,mid+1,r));
}
int queryxor(int rot,int pos){
	if (T[rot].l==T[rot].r)return T[rot].ans;pushdown(rot);int mid=(T[rot].l+T[rot].r)>>1;
	if (pos<=mid)return queryxor(rot<<1,pos);else return queryxor(rot<<1|1,pos);
}
int main(){
// 	freopen("imaginationland.in","r",stdin);
	// freopen("imaginationland.out","w",stdout);
	read(n);read(q);
	rep(i,1,n)read(b[i]);
	per(i,n,1)a[i]=b[i]^b[i-1];
	// rep(i,1,n)printf("%d ",b[i]);printf("\n");
	// rep(i,1,n)printf("%d ",a[i]);printf("\n");
	build(1,1,n);//return 0;
	rep(i,1,q){
		int op,l,r;read(op);read(l);read(r);
		if (op==2){
			int lxor=queryxor(1,l);//printf("%d %d\n",a[i],lxor);
			change(1,l,a[l]^lxor);//printf("%d\n",a[i]);
			if (n!=100)printf("%d\n",1<<(query(1,l,r)).count());
			else printf("%d %d %d\n",op,l,r);
			change(1,l,a[l]^lxor);
		}
		else {
			int v;read(v);
			if (n==100)printf("%d %d %d %d\n",op,l,r,v);
			change(1,l,v);if (r!=n)change(1,r+1,v);
			changexor(1,l,r,v);
		}
		// rep(k,1,n)printf("%d ",queryxor(1,k));printf("\n");
	}
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pi;
const double PI=acos(-1);
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define rep(i,a,b) for (int i=(a);i<=(b);i++)
#define per(i,a,b) for (int i=(a);i>=(b);i--)
#define Rep(i,a,b) for (int i=(a);i<(b);i++)
#define Per(i,a,b) for (int i=(a);i>(b);i--)
#define travel_set(it,a) for (set<int>::iterator (it)=(a).begin();(it)!=(a).end();(it)++)
#define travel_map(it,a) for (map<int>::iterator (it)=(a).begin();(it)!=(a).end();(it)++)
#define travel_vec(it,a) for (vector<int>::iterator (it)=(a).begin();(it)!=(a).end();(it)++)
#define p(x) cout << x << endl;
#define def cout << "find" << endl;
#define what_is(x) cout << #x << " is " << x << endl;
template <class T>T sqr(T x){return x*x;}
template <class T>T alex(T x){return (x>0)?x:-x;}
template <class T>void read(T&x){
	x=0;T f=1;char ch=getchar();
	while ((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
	if (ch=='-')f=-1,ch=getchar();
	while (ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
	x*=f;
}

//---------------------------------------------------head---------------------------------------------------

#define maxl 32
#define maxn 200005
int n,q;int a[maxn];
int b[maxn];
struct Node{
	int f[maxl];Node(){}
	void clear(){memset(f,0,sizeof(f));}
	void insert(int x){
		// printf("%d\n", x);
		per(i,31,0)if ((x>>i)&1){
			if (!f[i]){f[i]=x;break;}
			else x^=f[i];
		}
	}
	int count(){
		int res=0;
		rep(i,0,31)if (f[i])res++;
		return res;
	}
	void print(){
		rep(i,0,31)if (f[i])printf("(%d %d) ",i,f[i]);printf("\n");
	}
};
struct Tree{
	int l,r,ans,lzy;Node res;
}T[maxn<<2];
Node merge(Node x,Node y){
	Node res;res.clear();res=x;
	Rep(i,0,32)if (y.f[i])res.insert(y.f[i]);
	return res;
}
void update(int rot){
	T[rot].ans=T[rot<<1].ans^T[rot<<1|1].ans;
	T[rot].res=merge(T[rot<<1].res,T[rot<<1|1].res);
}
void pushdown(int rot){
	if (T[rot].lzy){
		T[rot<<1].ans^=T[rot].lzy;T[rot<<1|1].ans^=T[rot].lzy;
		T[rot<<1].lzy^=T[rot].lzy;T[rot<<1|1].lzy^=T[rot].lzy;
		T[rot].lzy=0;
	}
}
void build(int rot,int l,int r){
	// printf("%d %d %d %d %d\n",a[1],a[2],a[3],a[4],a[5]);
	T[rot].l=l;T[rot].r=r;if (l==r){T[rot].res.insert(a[l]);T[rot].ans=b[l];return;}int mid=(l+r)>>1;
	build(rot<<1,l,mid);build(rot<<1|1,mid+1,r);update(rot);
	// printf("%d %d:",l,r);T[rot].res.print();
}
void change(int rot,int pos,int x){
	if (T[rot].l==T[rot].r){
		T[rot].res.clear();a[pos]^=x;
		// printf("change %d %d %d\n",pos,a[pos],x);
		T[rot].res.insert(a[pos]);
		return;
	}
	pushdown(rot);
	int mid=(T[rot].l+T[rot].r)>>1;
	if (pos<=mid)change(rot<<1,pos,x);else change(rot<<1|1,pos,x);
	update(rot);
}
void changexor(int rot,int l,int r,int v){
	if (T[rot].l==l&&T[rot].r==r){
		T[rot].ans^=v;T[rot].lzy^=v;return;
	}
	pushdown(rot);int mid=(T[rot].l+T[rot].r)>>1;
	if (r<=mid)changexor(rot<<1,l,r,v);else if (l>mid)changexor(rot<<1|1,l,r,v);
	else changexor(rot<<1,l,mid,v),changexor(rot<<1|1,mid+1,r,v);update(rot);
}
Node query(int rot,int l,int r){
	if (T[rot].l==l&&T[rot].r==r){
		return T[rot].res;
	}pushdown(rot);int mid=(T[rot].l+T[rot].r)>>1;
	if (r<=mid)return query(rot<<1,l,r);else if (l>mid)return query(rot<<1|1,l,r);
	else return merge(query(rot<<1,l,mid),query(rot<<1|1,mid+1,r));
}
int queryxor(int rot,int pos){
	if (T[rot].l==T[rot].r)return T[rot].ans;pushdown(rot);int mid=(T[rot].l+T[rot].r)>>1;
	if (pos<=mid)return queryxor(rot<<1,pos);else return queryxor(rot<<1|1,pos);
}
int main(){
	read(n);read(q);
	rep(i,1,n)read(b[i]);
	per(i,n,1)a[i]=b[i]^b[i-1];
	// rep(i,1,n)printf("%d ",b[i]);printf("\n");
	// rep(i,1,n)printf("%d ",a[i]);printf("\n");
	build(1,1,n);//return 0;
	rep(i,1,q){
		int op,l,r;read(op);read(l);read(r);
		if (op==2){
			int lxor=queryxor(1,l);//printf("%d %d\n",a[i],lxor);
			change(1,l,a[l]^lxor);//printf("%d\n",a[i]);
			printf("%d\n",1<<(query(1,l,r)).count());
			change(1,l,a[l]^lxor);
		}
		else {
			int v;read(v);
			change(1,l,v);if (r!=n)change(1,r+1,v);
			changexor(1,l,r,v);
		}
		// rep(k,1,n)printf("%d ",queryxor(1,k));printf("\n");
	}
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pi;
const double PI=acos(-1);
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define rep(i,a,b) for (int i=(a);i<=(b);i++)
#define per(i,a,b) for (int i=(a);i>=(b);i--)
#define Rep(i,a,b) for (int i=(a);i<(b);i++)
#define Per(i,a,b) for (int i=(a);i>(b);i--)
#define travel_set(it,a) for (set<int>::iterator (it)=(a).begin();(it)!=(a).end();(it)++)
#define travel_map(it,a) for (map<int>::iterator (it)=(a).begin();(it)!=(a).end();(it)++)
#define travel_vec(it,a) for (vector<int>::iterator (it)=(a).begin();(it)!=(a).end();(it)++)
#define p(x) cout << x << endl;
#define def cout << "find" << endl;
#define what_is(x) cout << #x << " is " << x << endl;
template <class T>T sqr(T x){return x*x;}
template <class T>T alex(T x){return (x>0)?x:-x;}
template <class T>void read(T&x){
	x=0;T f=1;char ch=getchar();
	while ((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
	if (ch=='-')f=-1,ch=getchar();
	while (ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
	x*=f;
}

//---------------------------------------------------head---------------------------------------------------

#define maxl 32
#define maxn 200005
int n,q;int a[maxn];
int b[maxn];
struct Node{
	int f[maxl];Node(){}
	void clear(){memset(f,0,sizeof(f));}
	void insert(int x){
		// printf("%d\n", x);
		per(i,31,0)if ((x>>i)&1){
			if (!f[i]){f[i]=x;break;}
			else x^=f[i];
		}
	}
	int count(){
		int res=0;
		rep(i,0,31)if (f[i])res++;
		return res;
	}
	void print(){
		rep(i,0,31)if (f[i])printf("(%d %d) ",i,f[i]);printf("\n");
	}
};
struct Tree{
	int l,r,ans,lzy;Node res;
}T[maxn<<2];
Node merge(Node x,Node y){
	Node res;res.clear();res=x;
	Rep(i,0,32)if (y.f[i])res.insert(y.f[i]);
	return res;
}
void update(int rot){
	T[rot].ans=T[rot<<1].ans^T[rot<<1|1].ans;
	T[rot].res=merge(T[rot<<1].res,T[rot<<1|1].res);
}
void pushdown(int rot){
	if (T[rot].lzy){
		T[rot<<1].ans^=T[rot].lzy;T[rot<<1|1].ans^=T[rot].lzy;
		T[rot<<1].lzy^=T[rot].lzy;T[rot<<1|1].lzy^=T[rot].lzy;
		T[rot].lzy=0;
	}
}
void build(int rot,int l,int r){
	// printf("%d %d %d %d %d\n",a[1],a[2],a[3],a[4],a[5]);
	T[rot].l=l;T[rot].r=r;if (l==r){T[rot].res.insert(a[l]);T[rot].ans=b[l];return;}int mid=(l+r)>>1;
	build(rot<<1,l,mid);build(rot<<1|1,mid+1,r);update(rot);
	// printf("%d %d:",l,r);T[rot].res.print();
}
void change(int rot,int pos,int x){
	if (T[rot].l==T[rot].r){
		T[rot].res.clear();a[pos]^=x;
		// printf("change %d %d %d\n",pos,a[pos],x);
		T[rot].res.insert(a[pos]);
		return;
	}
	pushdown(rot);
	int mid=(T[rot].l+T[rot].r)>>1;
	if (pos<=mid)change(rot<<1,pos,x);else change(rot<<1|1,pos,x);
	update(rot);
}
void changexor(int rot,int l,int r,int v){
	if (T[rot].l==l&&T[rot].r==r){
		T[rot].ans^=v;T[rot].lzy^=v;return;
	}
	pushdown(rot);int mid=(T[rot].l+T[rot].r)>>1;
	if (r<=mid)changexor(rot<<1,l,r,v);else if (l>mid)changexor(rot<<1|1,l,r,v);
	else changexor(rot<<1,l,mid,v),changexor(rot<<1|1,mid+1,r,v);update(rot);
}
Node query(int rot,int l,int r){
	if (T[rot].l==l&&T[rot].r==r){
		return T[rot].res;
	}pushdown(rot);int mid=(T[rot].l+T[rot].r)>>1;
	if (r<=mid)return query(rot<<1,l,r);else if (l>mid)return query(rot<<1|1,l,r);
	else return merge(query(rot<<1,l,mid),query(rot<<1|1,mid+1,r));
}
int queryxor(int rot,int pos){
	if (T[rot].l==T[rot].r)return T[rot].ans;pushdown(rot);int mid=(T[rot].l+T[rot].r)>>1;
	if (pos<=mid)return queryxor(rot<<1,pos);else return queryxor(rot<<1|1,pos);
}
int main(){
	freopen("imaginationland.in","r",stdin);
	// freopen("imaginationland.out","w",stdout);
	read(n);read(q);
	rep(i,1,n)read(b[i]);
	per(i,n,1)a[i]=b[i]^b[i-1];
	// rep(i,1,n)printf("%d ",b[i]);printf("\n");
	// rep(i,1,n)printf("%d ",a[i]);printf("\n");
	build(1,1,n);//return 0;
	rep(i,1,q){
		int op,l,r;read(op);read(l);read(r);
		if (op==2){
		    printf("%d %d %d\n",op,l,r);
			int lxor=queryxor(1,l);//printf("%d %d\n",a[i],lxor);
			change(1,l,a[l]^lxor);//printf("%d\n",a[i]);
// 			printf("%d\n",1<<(query(1,l,r)).count());
			change(1,l,a[l]^lxor);
		}
		else {
			int v;read(v);
		    printf("%d %d %d %d\n",op,l,r,v);
			change(1,l,v);if (r!=n)change(1,r+1,v);
			changexor(1,l,r,v);
		}
		// rep(k,1,n)printf("%d ",queryxor(1,k));printf("\n");
	}
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pi;
const double PI=acos(-1);
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define rep(i,a,b) for (int i=(a);i<=(b);i++)
#define per(i,a,b) for (int i=(a);i>=(b);i--)
#define Rep(i,a,b) for (int i=(a);i<(b);i++)
#define Per(i,a,b) for (int i=(a);i>(b);i--)
#define travel_set(it,a) for (set<int>::iterator (it)=(a).begin();(it)!=(a).end();(it)++)
#define travel_map(it,a) for (map<int>::iterator (it)=(a).begin();(it)!=(a).end();(it)++)
#define travel_vec(it,a) for (vector<int>::iterator (it)=(a).begin();(it)!=(a).end();(it)++)
#define p(x) cout << x << endl;
#define def cout << "find" << endl;
#define what_is(x) cout << #x << " is " << x << endl;
template <class T>T sqr(T x){return x*x;}
template <class T>T alex(T x){return (x>0)?x:-x;}
template <class T>void read(T&x){
	x=0;T f=1;char ch=getchar();
	while ((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
	if (ch=='-')f=-1,ch=getchar();
	while (ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
	x*=f;
}

//---------------------------------------------------head---------------------------------------------------

#define maxl 32
#define maxn 200005
int n,q;int a[maxn];
int b[maxn];
struct Node{
	int f[maxl];Node(){}
	void clear(){memset(f,0,sizeof(f));}
	void insert(int x){
		// printf("%d\n", x);
		per(i,31,0)if ((x>>i)&1){
			if (!f[i]){f[i]=x;break;}
			else x^=f[i];
		}
	}
	int count(){
		int res=0;
		rep(i,0,31)if (f[i])res++;
		return res;
	}
	void print(){
		rep(i,0,31)if (f[i])printf("(%d %d) ",i,f[i]);printf("\n");
	}
};
struct Tree{
	int l,r,ans,lzy;Node res;
}T[maxn<<2];
Node merge(Node x,Node y){
	Node res;res.clear();res=x;
	Rep(i,0,32)if (y.f[i])res.insert(y.f[i]);
	return res;
}
void update(int rot){
	T[rot].ans=T[rot<<1].ans^T[rot<<1|1].ans;
	T[rot].res=merge(T[rot<<1].res,T[rot<<1|1].res);
}
void pushdown(int rot){
	if (T[rot].lzy){
		T[rot<<1].ans^=T[rot].lzy;T[rot<<1|1].ans^=T[rot].lzy;
		T[rot<<1].lzy^=T[rot].lzy;T[rot<<1|1].lzy^=T[rot].lzy;
		T[rot].lzy=0;
	}
}
void build(int rot,int l,int r){
	// printf("%d %d %d %d %d\n",a[1],a[2],a[3],a[4],a[5]);
	T[rot].l=l;T[rot].r=r;if (l==r){T[rot].res.insert(a[l]);T[rot].ans=b[l];return;}int mid=(l+r)>>1;
	build(rot<<1,l,mid);build(rot<<1|1,mid+1,r);update(rot);
	// printf("%d %d:",l,r);T[rot].res.print();
}
void change(int rot,int pos,int x){
	if (T[rot].l==T[rot].r){
		T[rot].res.clear();a[pos]^=x;
		// printf("change %d %d %d\n",pos,a[pos],x);
		T[rot].res.insert(a[pos]);
		return;
	}
	pushdown(rot);
	int mid=(T[rot].l+T[rot].r)>>1;
	if (pos<=mid)change(rot<<1,pos,x);else change(rot<<1|1,pos,x);
	update(rot);
}
void changexor(int rot,int l,int r,int v){
	if (T[rot].l==l&&T[rot].r==r){
		T[rot].ans^=v;T[rot].lzy^=v;return;
	}
	pushdown(rot);int mid=(T[rot].l+T[rot].r)>>1;
	if (r<=mid)changexor(rot<<1,l,r,v);else if (l>mid)changexor(rot<<1|1,l,r,v);
	else changexor(rot<<1,l,mid,v),changexor(rot<<1|1,mid+1,r,v);update(rot);
}
Node query(int rot,int l,int r){
	if (T[rot].l==l&&T[rot].r==r){
		return T[rot].res;
	}pushdown(rot);int mid=(T[rot].l+T[rot].r)>>1;
	if (r<=mid)return query(rot<<1,l,r);else if (l>mid)return query(rot<<1|1,l,r);
	else return merge(query(rot<<1,l,mid),query(rot<<1|1,mid+1,r));
}
int queryxor(int rot,int pos){
	if (T[rot].l==T[rot].r)return T[rot].ans;pushdown(rot);int mid=(T[rot].l+T[rot].r)>>1;
	if (pos<=mid)return queryxor(rot<<1,pos);else return queryxor(rot<<1|1,pos);
}
int main(){
	read(n);read(q);
	rep(i,1,n)read(b[i]);
	per(i,n,1)a[i]=b[i]^b[i-1];
	// rep(i,1,n)printf("%d ",b[i]);printf("\n");
	rep(i,1,n)printf("%d ",a[i]);printf("\n");
	build(1,1,n);//return 0;
	rep(i,1,q){
		int op,l,r;read(op);read(l);read(r);
		if (op==2){
			int lxor=queryxor(1,l);//printf("%d %d\n",a[i],lxor);
			change(1,l,a[l]^lxor);//printf("%d\n",a[i]);
			printf("%d\n",1<<(query(1,l,r)).count());
			change(1,l,a[l]^lxor);
		}
		else {
			int v;read(v);
			change(1,l,v);if (r!=n)change(1,r+1,v);
			changexor(1,l,r,v);
		}
		// rep(k,1,n)printf("%d ",queryxor(1,k));printf("\n");
	}
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pi;
const double PI=acos(-1);
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define rep(i,a,b) for (int i=(a);i<=(b);i++)
#define per(i,a,b) for (int i=(a);i>=(b);i--)
#define Rep(i,a,b) for (int i=(a);i<(b);i++)
#define Per(i,a,b) for (int i=(a);i>(b);i--)
#define travel_set(it,a) for (set<int>::iterator (it)=(a).begin();(it)!=(a).end();(it)++)
#define travel_map(it,a) for (map<int>::iterator (it)=(a).begin();(it)!=(a).end();(it)++)
#define travel_vec(it,a) for (vector<int>::iterator (it)=(a).begin();(it)!=(a).end();(it)++)
#define p(x) cout << x << endl;
#define def cout << "find" << endl;
#define what_is(x) cout << #x << " is " << x << endl;
template <class T>T sqr(T x){return x*x;}
template <class T>T alex(T x){return (x>0)?x:-x;}
template <class T>void read(T&x){
	x=0;T f=1;char ch=getchar();
	while ((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
	if (ch=='-')f=-1,ch=getchar();
	while (ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
	x*=f;
}

//---------------------------------------------------head---------------------------------------------------

#define maxl 32
#define maxn 200005
int n,q;int a[maxn];
int b[maxn];
struct Node{
	int f[maxl];Node(){}
	void clear(){memset(f,0,sizeof(f));}
	void insert(int x){
		// printf("%d\n", x);
		per(i,31,0)if ((x>>i)&1){
			if (!f[i]){f[i]=x;break;}
			else x^=f[i];
		}
	}
	int count(){
		int res=0;
		rep(i,0,31)if (f[i])res++;
		return res;
	}
	void print(){
		rep(i,0,31)if (f[i])printf("(%d %d) ",i,f[i]);printf("\n");
	}
};
struct Tree{
	int l,r,ans,lzy;Node res;
}T[maxn<<2];
Node merge(Node x,Node y){
	Node res;res.clear();res=x;
	Rep(i,0,32)if (y.f[i])res.insert(y.f[i]);
	return res;
}
void update(int rot){
	T[rot].ans=T[rot<<1].ans^T[rot<<1|1].ans;
	T[rot].res=merge(T[rot<<1].res,T[rot<<1|1].res);
}
void pushdown(int rot){
	if (T[rot].lzy){
		T[rot<<1].ans^=T[rot].lzy;T[rot<<1|1].ans^=T[rot].lzy;
		T[rot<<1].lzy^=T[rot].lzy;T[rot<<1|1].lzy^=T[rot].lzy;
		T[rot].lzy=0;
	}
}
void build(int rot,int l,int r){
	// printf("%d %d %d %d %d\n",a[1],a[2],a[3],a[4],a[5]);
	T[rot].l=l;T[rot].r=r;if (l==r){T[rot].res.insert(a[l]);T[rot].ans=b[l];return;}int mid=(l+r)>>1;
	build(rot<<1,l,mid);build(rot<<1|1,mid+1,r);update(rot);
	// printf("%d %d:",l,r);T[rot].res.print();
}
void change(int rot,int pos,int x){
	if (T[rot].l==T[rot].r){
		T[rot].res.clear();a[pos]^=x;
		// printf("change %d %d %d\n",pos,a[pos],x);
		T[rot].res.insert(a[pos]);
		return;
	}
	pushdown(rot);
	int mid=(T[rot].l+T[rot].r)>>1;
	if (pos<=mid)change(rot<<1,pos,x);else change(rot<<1|1,pos,x);
	update(rot);
}
void changexor(int rot,int l,int r,int v){
	if (T[rot].l==l&&T[rot].r==r){
		T[rot].ans^=v;T[rot].lzy^=v;return;
	}
	pushdown(rot);int mid=(T[rot].l+T[rot].r)>>1;
	if (r<=mid)changexor(rot<<1,l,r,v);else if (l>mid)changexor(rot<<1|1,l,r,v);
	else changexor(rot<<1,l,mid,v),changexor(rot<<1|1,mid+1,r,v);update(rot);
}
Node query(int rot,int l,int r){
	if (T[rot].l==l&&T[rot].r==r){
		return T[rot].res;
	}pushdown(rot);int mid=(T[rot].l+T[rot].r)>>1;
	if (r<=mid)return query(rot<<1,l,r);else if (l>mid)return query(rot<<1|1,l,r);
	else return merge(query(rot<<1,l,mid),query(rot<<1|1,mid+1,r));
}
int queryxor(int rot,int pos){
	if (T[rot].l==T[rot].r)return T[rot].ans;pushdown(rot);int mid=(T[rot].l+T[rot].r)>>1;
	if (pos<=mid)return queryxor(rot<<1,pos);else return queryxor(rot<<1|1,pos);
}
int main(){
	read(n);read(q);
	rep(i,1,n)read(b[i]);
	per(i,n,1)a[i]=b[i]^b[i-1];
	// rep(i,1,n)printf("%d ",b[i]);printf("\n");
	// rep(i,1,n)printf("%d ",a[i]);printf("\n");
	build(1,1,n);//return 0;
	rep(i,1,q){
		int op,l,r;read(op);read(l);read(r);
		if (op==2){
			int lxor=queryxor(1,l);//printf("%d %d\n",a[i],lxor);
			int v=a[l];
			change(1,l,a[l]^lxor);//printf("%d\n",a[i]);
			// if (l==40&&r==53)printf("%d\n",1<<(query(1,l,r)).count());
			printf("%d\n",1<<(query(1,l,r)).count());
			change(1,l,v^lxor);
		}
		else {
			int v;read(v);
			change(1,l,v);if (r!=n)change(1,r+1,v);
			changexor(1,l,r,v);
		}
		// rep(k,1,n)printf("%d ",queryxor(1,k));printf("\n");
	}
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pi;
const double PI=acos(-1);
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define rep(i,a,b) for (int i=(a);i<=(b);i++)
#define per(i,a,b) for (int i=(a);i>=(b);i--)
#define Rep(i,a,b) for (int i=(a);i<(b);i++)
#define Per(i,a,b) for (int i=(a);i>(b);i--)
#define travel_set(it,a) for (set<int>::iterator (it)=(a).begin();(it)!=(a).end();(it)++)
#define travel_map(it,a) for (map<int>::iterator (it)=(a).begin();(it)!=(a).end();(it)++)
#define travel_vec(it,a) for (vector<int>::iterator (it)=(a).begin();(it)!=(a).end();(it)++)
#define p(x) cout << x << endl;
#define def cout << "find" << endl;
#define what_is(x) cout << #x << " is " << x << endl;
template <class T>T sqr(T x){return x*x;}
template <class T>T alex(T x){return (x>0)?x:-x;}
template <class T>void read(T&x){
	x=0;T f=1;char ch=getchar();
	while ((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
	if (ch=='-')f=-1,ch=getchar();
	while (ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
	x*=f;
}

//---------------------------------------------------head---------------------------------------------------

#define maxl 32
#define maxn 200005
int n,q;int a[maxn];
int b[maxn];
struct Node{
	int f[maxl];Node(){}
	void clear(){memset(f,0,sizeof(f));}
	void insert(int x){
		// printf("%d\n", x);
		per(i,31,0)if ((x>>i)&1)
			if (!f[i]){f[i]=x;break;}
			else x^=f[i];
	}
	int count(){
		int res=0;
		rep(i,0,31)if (f[i])res++;
		return res;
	}
	void print(){
		rep(i,0,31)if (f[i])printf("(%d %d) ",i,f[i]);printf("\n");
	}
};
struct Tree{
	int l,r,ans,lzy;Node res;
}T[maxn<<2];
Node merge(Node x,Node y){
	Node res;res.clear();res=x;
	Rep(i,0,32)if (y.f[i])res.insert(y.f[i]);
	return res;
}
void update(int rot){
	T[rot].ans=T[rot<<1].ans^T[rot<<1|1].ans;
	T[rot].res=merge(T[rot<<1].res,T[rot<<1|1].res);
}
void pushdown(int rot){
	if (T[rot].lzy){
		T[rot<<1].ans^=T[rot].lzy;T[rot<<1|1].ans^=T[rot].lzy;
		T[rot<<1].lzy^=T[rot].lzy;T[rot<<1|1].lzy^=T[rot].lzy;
		T[rot].lzy=0;
	}
}
void build(int rot,int l,int r){
	// printf("%d %d %d %d %d\n",a[1],a[2],a[3],a[4],a[5]);
	T[rot].l=l;T[rot].r=r;if (l==r){T[rot].res.insert(a[l]);T[rot].ans=b[l];return;}int mid=(l+r)>>1;
	build(rot<<1,l,mid);build(rot<<1|1,mid+1,r);update(rot);
	// printf("%d %d:",l,r);T[rot].res.print();
}
void change(int rot,int pos,int x){
	if (T[rot].l==T[rot].r){
		T[rot].res.clear();a[pos]^=x;
		// printf("change %d %d %d\n",pos,a[pos],x);
		T[rot].res.insert(a[pos]);
		return;
	}
	pushdown(rot);
	int mid=(T[rot].l+T[rot].r)>>1;
	if (pos<=mid)change(rot<<1,pos,x);else change(rot<<1|1,pos,x);
	update(rot);
}
void changexor(int rot,int l,int r,int v){
	if (T[rot].l==l&&T[rot].r==r){
		T[rot].ans^=v;T[rot].lzy^=v;return;
	}
	pushdown(rot);int mid=(T[rot].l+T[rot].r)>>1;
	if (r<=mid)changexor(rot<<1,l,r,v);else if (l>mid)changexor(rot<<1|1,l,r,v);
	else changexor(rot<<1,l,mid,v),changexor(rot<<1|1,mid+1,r,v);update(rot);
}
Node query(int rot,int l,int r){
	if (T[rot].l==l&&T[rot].r==r){
		return T[rot].res;
	}pushdown(rot);int mid=(T[rot].l+T[rot].r)>>1;
	if (r<=mid)return query(rot<<1,l,r);else if (l>mid)return query(rot<<1|1,l,r);
	else return merge(query(rot<<1,l,mid),query(rot<<1|1,mid+1,r));
}
int queryxor(int rot,int pos){
	if (T[rot].l==T[rot].r)return T[rot].ans;pushdown(rot);int mid=(T[rot].l+T[rot].r)>>1;
	if (pos<=mid)return queryxor(rot<<1,pos);else return queryxor(rot<<1|1,pos);
}
int main(){
	read(n);read(q);
	rep(i,1,n)read(b[i]);
	per(i,n,1)a[i]=b[i]^b[i-1];
	// rep(i,1,n)printf("%d ",b[i]);printf("\n");
	// rep(i,1,n)printf("%d ",a[i]);printf("\n");
	build(1,1,n);//return 0;
	rep(i,1,q){
		int op,l,r;read(op);read(l);read(r);
		if (op==2){
			int lxor=queryxor(1,l);//printf("%d %d\n",a[i],lxor);
			change(1,l,a[l]^lxor);//printf("%d\n",a[i]);
			printf("%d\n",1<<(query(1,l,r)).count());
			change(1,l,a[l]^lxor);
		}
		else {
			int v;read(v);
			change(1,l,v);if (r!=n)change(1,r+1,v);
			changexor(1,l,r,v);
		}
		// rep(k,1,n)printf("%d ",queryxor(1,k));printf("\n");
	}
	return 0;
}


#include <iostream>

using namespace std;

struct tafin {
  int b[30];
  int nb;
  int p;
  int e;
  tafin() {
    p=nb=e=0;
  }
};

int n;
int m[100];

void fusiona(tafin &afin0,tafin &afin1,tafin &afin)
{
  n=0;
  for (int i=0;i<afin0.nb;i++)
    m[n++]=afin0.b[i];
  int s=afin0.p^afin0.e^afin1.p^afin1.e;
  m[n++]=s;
  for (int i=0;i<afin1.nb;i++)
    m[n++]=afin1.b[i]^s;
  int i=0,j=0;
  while (i<n and j<30) {
    int ii=i;
    while (ii<n and (m[ii]&(1<<j))==0) ii++;
    if (ii<n) {
      swap(m[i],m[ii]);
      for (ii=i+1;ii<n;ii++)
	if (m[ii]&(1<<j))
	  m[ii]^=m[i];
      i++;
      j++;
    } else j++;
  }
  afin.p=afin0.p^afin0.e;
  for (int ii=0;ii<i;ii++)
    afin.b[ii]=m[ii];
  afin.nb=i;
}

const int tope=1<<19;
const int primero=1<<18;
tafin v[tope];

void recalcula(int pos)
{
  fusiona(v[2*pos],v[2*pos+1],v[pos]);
}

void inserta(int pos0,int pos1,int val)
{
  pos0+=primero;
  pos1+=primero;
  if (pos0==pos1) {
    v[pos0].e^=val;
  } else {
    v[pos0].e^=val;
    v[pos1].e^=val;
    while (pos0/2!=pos1/2) {
      if (pos0%2==0) v[pos0+1].e^=val;
      pos0/=2;
      recalcula(pos0);
      if (pos1%2==1) v[pos1-1].e^=val;
      pos1/=2;
      recalcula(pos1);
    }
  }
  while (pos0>1) {
    pos0/=2;
    recalcula(pos0);
  }
}

tafin afin0,afin1,afinaux,afinsingle;

int calcula(int pos0,int pos1)
{
  pos0+=primero;
  pos1+=primero;
  afin0=v[pos0];
  if (pos0!=pos1) {
    afin1=v[pos1];
    while (pos0/2<pos1/2) {
      if (pos0%2==0) {
	fusiona(afin0,v[pos0+1],afinaux);
	afin0=afinaux;
      }
      pos0/=2;
      afin0.e^=v[pos0].e;
      if (pos1%2==1) {
	fusiona(afin1,v[pos1-1],afinaux);
	afin1=afinaux;
      }
      pos1/=2;
      afin1.e^=v[pos1].e;
    }
    fusiona(afin0,afin1,afinaux);
    afin0=afinaux;
  }
  while (pos0>1) {
    pos0/=2;
    afin0.e^=v[pos0].e;
  }
  fusiona(afin0,afinsingle,afinaux);
  return 1<<afinaux.nb;
}

int main()
{
  ios::sync_with_stdio(false);
  int n,q;
  cin>>n>>q;
  for (int i=1;i<=n;i++) {
    int a;
    cin>>a;
    inserta(i,i,a);
  }
  for (int caso=0;caso<q;caso++) {
    int tipo;
    cin>>tipo;
    if (tipo==1) {
      int l,r,k;
      cin>>l>>r>>k;
      inserta(l,r,k);
    } else {
      int l,r;
      cin>>l>>r;
      cout<<calcula(l,r)<<endl;
    }
  }
}


#include<bits/stdc++.h>
using namespace std;

const int N = 2e5 + 5;

int n, m, a[N], b[N], ob[4 * N];
vector < int > cur;

inline void add(int x){
    for(auto it : cur){
        x = min(x, x ^ it);
    }
    if(!x){
        return;
    }
    for(auto &it : cur){
        it = min(it, it ^ x);
    }
    cur.push_back(x);
    sort(cur.rbegin(), cur.rbegin());
}

struct item{
    vector < int > basis;
    int le;
};
item t[4 * N], ans;

inline item mrg(item a, item b){
    cur.clear();
    for(int x : a.basis){
        add(x);
    }
    for(int x : b.basis){
        add(x);
    }
    //cout << a.le << " " << b.le << "\n";
    add(a.le ^ b.le);
    item nxt;
    nxt.basis = cur;
    nxt.le = a.le;
    return nxt;
}

void build(int v, int l, int r){
    if(l == r){
        t[v].le = a[l];
        return;
    }
    int mid = (r + l) >> 1;
    build(v + v, l, mid);
    build(v + v + 1, mid + 1, r);
    t[v] = mrg(t[v + v], t[v + v + 1]);
}

inline void push(int v){
    ob[v + v] ^= ob[v];
    ob[v + v + 1] ^= ob[v];
    t[v + v].le ^= ob[v];
    t[v + v + 1].le ^= ob[v];
    ob[v] = 0;
}

void update(int v, int l, int r, int tl, int tr, int val){
    if(l > r || l > tr || tl > r){
        return;
    }
    if(tl <= l && r <= tr){
        ob[v] ^= val;
        t[v].le ^= val;
        return;
    }
    int mid = (r + l) >> 1;
    push(v);
    update(v + v, l, mid, tl, tr, val);
    update(v + v + 1, mid + 1, r, tl, tr, val);
    t[v] = mrg(t[v + v], t[v + v + 1]);
}

void get(int v, int l, int r, int tl, int tr){
    if(l > r || l > tr || tl > r){
        return;
    }
    if(tl <= l && r <= tr){
        ans = mrg(ans, t[v]);
        return;
    }
    int mid = (r + l) >> 1;
    push(v);
    get(v + v, l, mid, tl, tr);
    get(v + v + 1, mid + 1, r, tl, tr);
}

int main(){
    ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin >> n >> m;
    for(int i = 1; i <= n; i++){
        cin >> a[i];
    }
    build(1, 1, n);
    for(int i = 1; i <= m; i++){
        int type, l, r, k;
        cin >> type >> l >> r;
        if(type == 1){
            cin >> k;
            update(1, 1, n, l, r, k);
        }
        else{
            ans.basis.clear();
            ans.le = 0;
            get(1, 1, n, l, r);
            cout << (1ll << ans.basis.size()) << "\n";
        }
    }
}


#include <bits/stdc++.h>
using namespace std;

inline int gi()
{
	char c = getchar();
	while(c < '0' || c > '9') c = getchar();
	int sum = 0;
	while('0' <= c && c <= '9') sum = sum * 10 + c - 48, c = getchar();
	return sum;
}

const int maxn = 200005;

int n, q, a[maxn], b[maxn], sum[maxn];
int p[maxn * 4][30], tmp[30];

#define lch (s << 1)
#define rch (s << 1 | 1)
#define mid ((l + r) >> 1)

void merge(int *p, int *p1, int *p2)
{
	memcpy(p, p1, sizeof(int) * 30);
	for (int i = 29, v; ~i; --i) {
		if (!p2[i]) continue;
		v = p2[i];
		for (int j = 29; ~j; --j)
			if ((v >> j) & 1) {
				if (!p[j]) {p[j] = v; break;}
				else v ^= p[j];
			}
	}
}

void build(int s, int l, int r)
{
	if (l == r) {
		for (int i = 29; ~i; --i)
			if ((a[l] >> i) & 1) return p[s][i] = a[l], void();
		return ;
	}
	build(lch, l, mid);
	build(rch, mid + 1, r);
	merge(p[s], p[lch], p[rch]);
}

void modify(int s, int l, int r, int x, int v)
{
	if (l == r) {
		a[l] ^= v;
		memset(p[s], 0, sizeof(p[s]));
		for (int i = 29; ~i; --i)
			if ((a[l] >> i) & 1) return p[s][i] = a[l], void();
		return ;
	}
	if (x <= mid) modify(lch, l, mid, x, v);
	else modify(rch, mid + 1, r, x, v);
	merge(p[s], p[lch], p[rch]);
}

void query(int s, int l, int r, int ql, int qr, int *tmp)
{
	if (ql <= l && r <= qr) return merge(tmp, tmp, p[s]);
	if (ql <= mid) query(lch, l, mid, ql, qr, tmp);
	if (qr > mid) query(rch, mid + 1, r, ql, qr, tmp);
}

void insert(int x, int v)
{
	while (x <= n) {
		sum[x] ^= v;
		x += x & (-x);
	}
}

int query(int x)
{
	int res = 0;
	while (x) {
		res ^= sum[x];
		x -= x & (-x);
	}
	return res;
}

int main()
{
	n = gi(); q = gi();
	for (int i = 1; i <= n; ++i)
		b[i] = gi(), insert(i, b[i]), insert(i + 1, b[i]);
	for (int i = n; i >= 1; --i) a[i] = b[i] ^ b[i - 1];

	build(1, 1, n);

	int op, l, r, v;
	while (q--) {
		op = gi(); l = gi(); r = gi();
		if (op == 1) {
			v = gi();
			modify(1, 1, n, l, v);
			if (r < n) modify(1, 1, n, r + 1, v);
			insert(l, v); insert(r + 1, v);
		} else {
			memset(tmp, 0, sizeof(tmp));
			if (l < r) query(1, 1, n, l + 1, r, tmp);
			int ans = 1, v = query(l);
			for (int j = 29; ~j; --j)
				if ((v >> j) & 1) {
					if (!tmp[j]) {tmp[j] = v; break;}
					else v ^= tmp[j];
				}
			for (int i = 29; ~i; --i)
				if (tmp[i]) ans <<= 1;
			printf("%d\n", ans);
		}
	}

	return 0;
}


#include <bits/stdc++.h>
using namespace std;

inline int gi()
{
	char c = getchar();
	while(c < '0' || c > '9') c = getchar();
	int sum = 0;
	while('0' <= c && c <= '9') sum = sum * 10 + c - 48, c = getchar();
	return sum;
}

const int maxn = 200005;

int n, q, a[maxn];
int p[maxn * 4][31], tmp[31];

#define lch (s << 1)
#define rch (s << 1 | 1)
#define mid ((l + r) >> 1)

void merge(int *p, int *p1, int *p2)
{
	memcpy(p, p1, sizeof(int) * 30);
	p[30] |= p2[30];
	for (int i = 29, v; ~i; --i) {
		if (!p2[i]) continue;
		v = p2[i];
		for (int j = 29; ~j; --j)
			if ((v >> j) & 1) {
				if (!p[j]) {p[j] = v; break;}
				else v ^= p[j];
			}
		if (!v) p[30] = 1;
	}
}

void build(int s, int l, int r)
{
	if (l == r) {
		for (int i = 29; ~i; --i)
			if ((a[l] >> i) & 1) return p[s][i] = a[l], void();
		p[s][30] = 1; return ;
	}
	build(lch, l, mid);
	build(rch, mid + 1, r);
	merge(p[s], p[lch], p[rch]);
}

void modify(int s, int l, int r, int x, int v)
{
	if (l == r) {
		a[l] ^= v;
		memset(p[s], 0, sizeof(p[s]));
		for (int i = 29; ~i; --i)
			if ((a[l] >> i) & 1) return p[s][i] = a[l], void();
		p[s][30] = 1; return ;
	}
	if (x <= mid) modify(lch, l, mid, x, v);
	else modify(rch, mid + 1, r, x, v);
	merge(p[s], p[lch], p[rch]);
}

void query(int s, int l, int r, int ql, int qr, int *tmp)
{
	if (ql <= l && r <= qr) return merge(tmp, tmp, p[s]);
	if (ql <= mid) query(lch, l, mid, ql, qr, tmp);
	if (qr > mid) query(rch, mid + 1, r, ql, qr, tmp);
}

int main()
{
	n = gi(); q = gi();
	for (int i = 1; i <= n; ++i) a[i] = gi(), a[i] ^= a[i - 1];

	if (2 <= n) build(1, 2, n);

	int op, l, r, v;
	while (q--) {
		op = gi(); l = gi(); r = gi();
		if (op == 1) v = gi(), modify(1, 2, n, l, v), modify(1, 2, n, r + 1, v);
		else {
			memset(tmp, 0, sizeof(tmp));
			if (l < r) query(1, 2, n, l + 1, r, tmp);
			int ans = 1, v = a[l];
			for (int j = 29; ~j; --j)
				if ((v >> j) & 1) {
					if (!tmp[j]) {tmp[j] = v; break;}
					else v ^= tmp[j];
				}
			if (!v) tmp[30] = 1;
			for (int i = 29; ~i; --i)
				if (tmp[i]) ans <<= 1;
			printf("%d\n", ans - 1 + tmp[30]);
		}
	}

	return 0;
}


#include <bits/stdc++.h>
using namespace std;

inline int gi()
{
	char c = getchar();
	while(c < '0' || c > '9') c = getchar();
	int sum = 0;
	while('0' <= c && c <= '9') sum = sum * 10 + c - 48, c = getchar();
	return sum;
}

const int maxn = 200005;

int n, q, a[maxn];
int p[maxn * 4][30], tmp[30];

#define lch (s << 1)
#define rch (s << 1 | 1)
#define mid ((l + r) >> 1)

void merge(int *p, int *p1, int *p2)
{
	memcpy(p, p1, sizeof(int) * 30);
	for (int i = 29, v; ~i; --i) {
		if (!p2[i]) continue;
		v = p2[i];
		for (int j = 29; ~j; --j)
			if ((v >> j) & 1) {
				if (!p[j]) {p[j] = v; break;}
				else v ^= p[j];
			}
	}
}

void build(int s, int l, int r)
{
	if (l == r) {
		for (int i = 29; ~i; --i)
			if ((a[l] >> i) & 1) return p[s][i] = a[l], void();
		return ;
	}
	build(lch, l, mid);
	build(rch, mid + 1, r);
	merge(p[s], p[lch], p[rch]);
}

void modify(int s, int l, int r, int x, int v)
{
	if (l == r) {
		a[l] ^= v;
		memset(p[s], 0, sizeof(p[s]));
		for (int i = 29; ~i; --i)
			if ((a[l] >> i) & 1) return p[s][i] = a[l], void();
		return ;
	}
	if (x <= mid) modify(lch, l, mid, x, v);
	else modify(rch, mid + 1, r, x, v);
	merge(p[s], p[lch], p[rch]);
}

void query(int s, int l, int r, int ql, int qr, int *tmp)
{
	if (ql <= l && r <= qr) return merge(tmp, tmp, p[s]);
	if (ql <= mid) query(lch, l, mid, ql, qr, tmp);
	if (qr > mid) query(rch, mid + 1, r, ql, qr, tmp);
}

int main()
{
	n = gi(); q = gi();
	for (int i = 1; i <= n; ++i) a[i] = gi(), a[i] ^= a[i - 1];

	if (2 <= n) build(1, 1, n);

	int op, l, r, v;
	while (q--) {
		op = gi(); l = gi(); r = gi();
		if (op == 1) {
			v = gi();
			modify(1, 1, n, l, v);
			if (r < n) modify(1, 1, n, r + 1, v);
		} else {
			memset(tmp, 0, sizeof(tmp));
			if (l < r) query(1, 1, n, l + 1, r, tmp);
			int ans = 1, v = a[l] ^ a[l - 1];
			for (int j = 29; ~j; --j)
				if ((v >> j) & 1) {
					if (!tmp[j]) {tmp[j] = v; break;}
					else v ^= tmp[j];
				}
			for (int i = 29; ~i; --i)
				if (tmp[i]) ans <<= 1;
			printf("%d\n", ans);
		}
	}

	return 0;
}


#include <bits/stdc++.h>
using namespace std;

inline int gi()
{
	char c = getchar();
	while(c < '0' || c > '9') c = getchar();
	int sum = 0;
	while('0' <= c && c <= '9') sum = sum * 10 + c - 48, c = getchar();
	return sum;
}

const int maxn = 200005;

int n, q, a[maxn];
int p[maxn * 4][31], tmp[31];

#define lch (s << 1)
#define rch (s << 1 | 1)
#define mid ((l + r) >> 1)

void merge(int *p, int *p1, int *p2)
{
	memcpy(p, p1, sizeof(int) * 30);
	p[30] |= p2[30];
	for (int i = 29, v; ~i; --i) {
		if (!p2[i]) continue;
		v = p2[i];
		for (int j = 29; ~j; --j)
			if ((v >> j) & 1) {
				if (!p[j]) {p[j] = v; break;}
				else v ^= p[j];
			}
		if (!v) p[30] = 1;
	}
}

void build(int s, int l, int r)
{
	if (l == r) {
		for (int i = 29; ~i; --i)
			if ((a[l] >> i) & 1) return p[s][i] = a[l], void();
		p[s][30] = 1; return ;
	}
	build(lch, l, mid);
	build(rch, mid + 1, r);
	merge(p[s], p[lch], p[rch]);
}

void modify(int s, int l, int r, int x, int v)
{
	if (l == r) {
		a[l] ^= v;
		memset(p[s], 0, sizeof(p[s]));
		for (int i = 29; ~i; --i)
			if ((a[l] >> i) & 1) return p[s][i] = a[l], void();
		p[s][30] = 1; return ;
	}
	if (x <= mid) modify(lch, l, mid, x, v);
	else modify(rch, mid + 1, r, x, v);
	merge(p[s], p[lch], p[rch]);
}

void query(int s, int l, int r, int ql, int qr, int *tmp)
{
	if (ql <= l && r <= qr) return merge(tmp, tmp, p[s]);
	if (ql <= mid) query(lch, l, mid, ql, qr, tmp);
	if (qr > mid) query(rch, mid + 1, r, ql, qr, tmp);
}

int main()
{
	n = gi(); q = gi();
	for (int i = 1; i <= n; ++i) a[i] = gi(), a[i] ^= a[i - 1];

	build(1, 2, n);

	int op, l, r, v;
	while (q--) {
		op = gi(); l = gi(); r = gi();
		if (op == 1) v = gi(), modify(1, 2, n, l, v), modify(1, 2, n, r + 1, v);
		else {
			memset(tmp, 0, sizeof(tmp));
			if (l < r) query(1, 2, n, l + 1, r, tmp);
			int ans = 1, v = a[l];
			for (int j = 29; ~j; --j)
				if ((v >> j) & 1) {
					if (!tmp[j]) {tmp[j] = v; break;}
					else v ^= tmp[j];
				}
			if (!v) tmp[30] = 1;
			for (int i = 29; ~i; --i)
				if (tmp[i]) ans <<= 1;
			printf("%d\n", ans - 1 + tmp[30]);
		}
	}

	return 0;
}


#include <cstdio>
#include <cstring>
const int maxn=2e5+100;
const int NUM=32;
int n,q;
int a[maxn],c[maxn];
int pow_2[NUM-1];

struct node
{
	int c[NUM];
	int l,r,val;
	void init()
	{
		memset(c,0,sizeof(c));
	}
	void ins(int x)
	{
		for(int i=NUM-1;i>=0;i--)
		{
			if((x>>i)&1)
			{
				if(c[i])
					x^=c[i];
				else
				{
					c[i]=x;
					return;
				}
			}
		}
	}
}SegmentTree[maxn<<2];

struct nodes
{
	int l,r,val,lazy;
	void update(int x)
	{
		lazy^=x;
		if((r-l+1)&1) val^=x;
	}
}Tree[maxn<<2];

int lowbit(int x)
{
    return x&(-x);
}

int Query(int id)
{
    int ans=0;
    while(id)
    {
        ans^=c[id];
        id-=lowbit(id);
    }
    return ans;
}

void Update(int id,int x)
{
    while(id<=n)
    {
        c[id]^=x;
        id+=lowbit(id);
    }
}

void push_up(int id)
{
	for(int i=0;i<NUM;i++)
	{
		SegmentTree[id].ins(SegmentTree[id<<1].c[i]);
		SegmentTree[id].ins(SegmentTree[id<<1|1].c[i]);
	}
}

void build(int id,int l,int r)
{
	SegmentTree[id].l=l;SegmentTree[id].r=r;SegmentTree[id].init();
	if(l==r)
	{
		SegmentTree[id].ins(a[l]);
		SegmentTree[id].val=a[l];
	}
	else
	{
		int mid=(l+r)>>1;
		build(id<<1,l,mid);
		build(id<<1|1,mid+1,r);
		push_up(id);
	}
}

void update(int id,int pos,int x)
{
	int L=SegmentTree[id].l,R=SegmentTree[id].r;
	if(L==R)
	{
		int val=SegmentTree[id].val;
		SegmentTree[id].init();
		SegmentTree[id].ins(x^val);
		SegmentTree[id].val=x^val;
		return;
	}
	int mid=(L+R)>>1;
	if(pos<=mid) update(id<<1,pos,x);
	else update(id<<1|1,pos,x);
	push_up(id);
}

node query(int id,int l,int r)
{
	int L=SegmentTree[id].l,R=SegmentTree[id].r;
	if(L==R) return SegmentTree[id];
	int mid=(L+R)>>1;
	node ans;
	ans.init();
	if(l<=mid)
	{
		node res=query(id<<1,l,r);
		for(int i=0;i<NUM;i++)
			ans.ins(res.c[i]);
	}
	if(r>mid)
	{
		node res=query(id<<1|1,l,r);
		for(int i=0;i<NUM;i++)
			ans.ins(res.c[i]);
	}
	return ans;
}

int getint()
{
    char ch = getchar(); int ret = 0;
    while (ch < '0' || '9' < ch) ch = getchar();
    while ('0' <= ch && ch <= '9')
        ret = ret*10 + ch - '0',ch = getchar();
    return ret;
}

int main()
{
    //freopen("587E.txt","r",stdin);
	pow_2[0]=1;
    for(int i=1;i<NUM-1;i++)
        pow_2[i]=2*pow_2[i-1];
	//scanf("%d %d",&n,&q);
	n=getint();
	q=getint();
	for(int i=1;i<=n;i++)
	{
		//scanf("%d",&a[i]);
		a[i]=getint();
	}

	for(int i=n;i>=1;i--)
		a[i]^=a[i-1];
	build(1,1,n);
	for(int i=1;i<=n;i++)
        Update(i,a[i]);
	while(q--)
	{
		int op;
		//scanf("%d",&op);
		op=getint();
		if(op==1)
		{
			int l,r,k;
			//scanf("%d %d %d",&l,&r,&k);
			l=getint();
			r=getint();
			k=getint();
			update(1,l,k);
			Update(l,k);
			if(r!=n)
            {
                update(1,r+1,k);
                Update(r+1,k);
            }
		}
		else
		{
			int l,r;
			int ans=0;
			//scanf("%d %d",&l,&r);
			l=getint();
			r=getint();
			node res;
			res.init();
			if(l<r)
                res=query(1,l+1,r);
            res.ins(Query(l));
            for(int i=0;i<NUM;i++)
                ans+=res.c[i]>0;
			printf("%d\n",pow_2[ans]);
		}
	}
	return 0;
}


#include <cstdio>
#include <cstring>
const int maxn=2e5+100;
const int NUM=32;
int n,q;
int a[maxn],c[maxn];
int pow_2[NUM-1];

struct node
{
	int c[NUM];
	int l,r,val;
	void init()
	{
		memset(c,0,sizeof(c));
	}
	void ins(int x)
	{
		for(int i=NUM-1;i>=0;i--)
		{
			if((x>>i)&1)
			{
				if(c[i])
					x^=c[i];
				else
				{
					c[i]=x;
					return;
				}
			}
		}
	}
}SegmentTree[maxn<<2];

struct nodes
{
	int l,r,val,lazy;
	void update(int x)
	{
		lazy^=x;
		if((r-l+1)&1) val^=x;
	}
}Tree[maxn<<2];

int lowbit(int x)
{
    return x&(-x);
}

int Query(int id)
{
    int ans=0;
    while(id)
    {
        ans^=c[id];
        id-=lowbit(id);
    }
    return ans;
}

void Update(int id,int x)
{
    while(id<=n)
    {
        c[id]^=x;
        id+=lowbit(id);
    }
}

void push_up(int id)
{
	for(int i=0;i<NUM;i++)
	{
		SegmentTree[id].ins(SegmentTree[id<<1].c[i]);
		SegmentTree[id].ins(SegmentTree[id<<1|1].c[i]);
	}
}

void build(int id,int l,int r)
{
	SegmentTree[id].l=l;SegmentTree[id].r=r;SegmentTree[id].init();
	if(l==r)
	{
		SegmentTree[id].ins(a[l]);
		SegmentTree[id].val=a[l];
	}
	else
	{
		int mid=(l+r)>>1;
		build(id<<1,l,mid);
		build(id<<1|1,mid+1,r);
		push_up(id);
	}
}

void update(int id,int pos,int x)
{
	int L=SegmentTree[id].l,R=SegmentTree[id].r;
	if(L==R)
	{
		int val=SegmentTree[id].val;
		SegmentTree[id].init();
		SegmentTree[id].ins(x^val);
		SegmentTree[id].val=x^val;
		return;
	}
	int mid=(L+R)>>1;
	if(pos<=mid) update(id<<1,pos,x);
	else update(id<<1|1,pos,x);
	push_up(id);
}

node query(int id,int l,int r)
{
	int L=SegmentTree[id].l,R=SegmentTree[id].r;
	if(L==R) return SegmentTree[id];
	int mid=(L+R)>>1;
	node ans;
	ans.init();
	if(l<=mid)
	{
		node res=query(id<<1,l,r);
		for(int i=0;i<NUM;i++)
			ans.ins(res.c[i]);
	}
	if(r>mid)
	{
		node res=query(id<<1|1,l,r);
		for(int i=0;i<NUM;i++)
			ans.ins(res.c[i]);
	}
	return ans;
}

int main()
{
    //freopen("587E.txt","r",stdin);
	pow_2[0]=1;
    for(int i=1;i<NUM-1;i++)
        pow_2[i]=2*pow_2[i-1];
	scanf("%d %d",&n,&q);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	for(int i=n;i>=1;i--)
		a[i]^=a[i-1];
	build(1,1,n);
	for(int i=1;i<=n;i++)
        Update(i,a[i]);
	while(q--)
	{
		int op;
		scanf("%d",&op);
		if(op==1)
		{
			int l,r,k;
			scanf("%d %d %d",&l,&r,&k);
			update(1,l,k);
			Update(l,k);
			if(r!=n)
            {
                update(1,r+1,k);
                Update(r+1,k);
            }
		}
		else
		{
			int l,r;
			int ans=0;
			scanf("%d %d",&l,&r);
			node res;
			res.init();
			res.ins(Query(l));
            if(l<r)
            {
                node tmp=query(1,l+1,r);
                for(int i=0;i<NUM;i++)
                    res.ins(tmp.c[i]);
            }
            for(int i=0;i<NUM;i++)
                ans+=res.c[i]>0;
			printf("%d\n",pow_2[ans]);
		}
	}
	return 0;
}


#include <cstdio>
#include <cstring>
const int maxn=2e5+100;
const int NUM=32;
int n,q;
int a[maxn],c[maxn];
int pow_2[NUM-1];

struct node
{
	int c[NUM];
	int l,r,val;
	void init()
	{
		memset(c,0,sizeof(c));
	}
	void ins(int x)
	{
		for(int i=NUM-1;i>=0;i--)
		{
			if((x>>i)&1)
			{
				if(c[i])
					x^=c[i];
				else
				{
					c[i]=x;
					return;
				}
			}
		}
	}
}SegmentTree[maxn<<2];

struct nodes
{
	int l,r,val,lazy;
	void update(int x)
	{
		lazy^=x;
		if((r-l+1)&1) val^=x;
	}
}Tree[maxn<<2];

int lowbit(int x)
{
    return x&(-x);
}

int Query(int id)
{
    int ans=0;
    while(id)
    {
        ans^=c[id];
        id-=lowbit(id);
    }
    return ans;
}

void Update(int id,int x)
{
    while(id<=n)
    {
        c[id]^=x;
        id+=lowbit(id);
    }
}

void push_up(int id)
{
	for(int i=0;i<NUM;i++)
	{
		SegmentTree[id].ins(SegmentTree[id<<1].c[i]);
		SegmentTree[id].ins(SegmentTree[id<<1|1].c[i]);
	}
}

void build(int id,int l,int r)
{
	SegmentTree[id].l=l;SegmentTree[id].r=r;SegmentTree[id].init();
	if(l==r)
	{
		SegmentTree[id].ins(a[l]);
		SegmentTree[id].val=a[l];
        Update(l,a[l]);
	}
	else
	{
		int mid=(l+r)>>1;
		build(id<<1,l,mid);
		build(id<<1|1,mid+1,r);
		push_up(id);
	}
}

void update(int id,int pos,int x)
{
	int L=SegmentTree[id].l,R=SegmentTree[id].r;
	if(L==R)
	{
		int val=SegmentTree[id].val;
		SegmentTree[id].init();
		SegmentTree[id].ins(x^val);
		SegmentTree[id].val=x^val;
		Update(pos,x);
		return;
	}
	int mid=(L+R)>>1;
	if(pos<=mid) update(id<<1,pos,x);
	else update(id<<1|1,pos,x);
	push_up(id);
}

node query(int id,int l,int r)
{
	int L=SegmentTree[id].l,R=SegmentTree[id].r;
	if(l<=L&&R<=r) return SegmentTree[id];
	int mid=(L+R)>>1;
	node ans;
	ans.init();
	if(l<=mid)
	{
		node res=query(id<<1,l,r);
		for(int i=0;i<NUM;i++)
			ans.ins(res.c[i]);
	}
	if(r>mid)
	{
		node res=query(id<<1|1,l,r);
		for(int i=0;i<NUM;i++)
			ans.ins(res.c[i]);
	}
	return ans;
}

int main()
{
    //freopen("587E.txt","r",stdin);
	pow_2[0]=1;
    for(int i=1;i<NUM-1;i++)
        pow_2[i]=2*pow_2[i-1];
	scanf("%d %d",&n,&q);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	for(int i=n;i>=1;i--)
		a[i]^=a[i-1];
	build(1,1,n);
	while(q--)
	{
		int op;
		scanf("%d",&op);
		if(op==1)
		{
			int l,r,k;
			scanf("%d %d %d",&l,&r,&k);
			update(1,l,k);
			if(r!=n)
                update(1,r+1,k);
		}
		else
		{
			int l,r;
			int ans=0;
			scanf("%d %d",&l,&r);
			node res;
			res.init();
			if(l<r)
                res=query(1,l+1,r);
            res.ins(Query(l));
            for(int i=0;i<NUM;i++)
                ans+=res.c[i]>0;
			printf("%d\n",pow_2[ans]);
		}
	}
	return 0;
}


    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<vector>
    #include<queue>
    #include<set>
    #include<map>
    #include<stack>
    #include<bitset>
    #include<ext/pb_ds/priority_queue.hpp>
    using namespace std;

    const int maxn = 2E5 + 20;
    const int T = 4;
    const int N = 30;

    struct data{
        int a[N]; data(){memset(a,0,sizeof(a));}
        data operator + (const data &b)
        {
            data c;
            for (int i = 0; i < N; i++) c.a[i] = a[i];
            for (int i = 0; i < N; i++)
            {
                if (!b.a[i]) continue; int x = b.a[i];
                for (int j = i; j < N; j++)
                    if (x & (1<<j))
                    {
                        if (c.a[j]) x ^= c.a[j];
                        else {c.a[j] = x; break;}
                    }
            }
            return c;
        }
    }c[maxn*T],ret;

    int n,m,mi[N + 1],A[maxn],sum[maxn];

    int getint()
    {
        char ch = getchar(); int ret = 0;
        while (ch < '0' || '9' < ch) ch = getchar();
        while ('0' <= ch && ch <= '9')
            ret = ret*10 + ch - '0',ch = getchar();
        return ret;
    }

    void Build(int o,int l,int r)
    {
        if (l == r)
        {
            for (int i = l; i <= n; i += i&-i) sum[i] ^= A[l];
            for (int i = 0; i < N; i++)
                if (A[l] & (1<<i)) {c[o].a[i] = A[l]; break;}
            return;
        }
        int mid = (l + r) >> 1;
        Build(o<<1,l,mid); Build(o<<1|1,mid+1,r);
        c[o] = c[o<<1] + c[o<<1|1];
    }

    void Modify(int o,int l,int r,int pos,int t)
    {
        if (l == r)
        {
            memset(c[o].a,0,sizeof(c[o].a)); A[l] ^= t;
            for (int i = l; i <= n; i += i&-i) sum[i] ^= t;
            for (int i = 0; i < N; i++)
                if (A[l] & (1<<i)) {c[o].a[i] = A[l]; break;}
            return;
        }
        int mid = (l + r) >> 1;
        if (pos <= mid) Modify(o<<1,l,mid,pos,t);
        else Modify(o<<1|1,mid+1,r,pos,t);
        c[o] = c[o<<1] + c[o<<1|1];
    }

    void Query(int o,int l,int r,int ql,int qr)
    {
        if (ql <= l && r <= qr) {ret = ret + c[o]; return;}
        int mid = (l + r) >> 1;
        if (ql <= mid) Query(o<<1,l,mid,ql,qr);
        if (qr > mid) Query(o<<1|1,mid+1,r,ql,qr);
    }

    int Sum(int pos)
    {
        int ret = 0;
        for (int i = pos; i > 0; i -= i&-i) ret ^= sum[i];
        return ret;
    }

    int main()
    {

        n = getint(); m = getint();
        for (int i = 1; i <= n; i++) A[i] = getint();
        for (int i = n; i > 1; i--) A[i] = A[i] ^ A[i - 1];
        Build(1,1,n); mi[0] = 1;
        for (int i = 1; i <= N; i++) mi[i] = mi[i-1] << 1;

        while (m--)
        {
            int typ = getint(),l,r;
            l = getint(); r = getint();
            if (typ == 1)
            {
                int k = getint(); Modify(1,1,n,l,k);
                if (r < n) Modify(1,1,n,r + 1,k);
            }
            else
            {
                memset(ret.a,0,sizeof(ret.a));
                int tot = Sum(l),Ans = 0;
                for (int i = 0; i < N; i++)
                    if (tot & (1<<i)) {ret.a[i] = tot; break;}
                if (l < r) Query(1,1,n,l + 1,r);
                for (int i = 0; i < N; i++) if (ret.a[i]) ++Ans;
                printf("%d\n",mi[Ans]);
            }
        }
        return 0;
    }


#include <cstdio>
#include <cstring>
const int maxn=2e5+100;
const int NUM=32;
int n,q;
int a[maxn],c[maxn];
int pow_2[NUM-1];

struct node
{
	int c[NUM];
	int l,r,val;
	void init()
	{
		memset(c,0,sizeof(c));
	}
	void ins(int x)
	{
		if(!x) return;
		for(int i=NUM-1;i>=0;i--)
		{
			if((x>>i)&1)
			{
				if(c[i])
					x^=c[i];
				else
				{
					c[i]=x;
					return;
				}
			}
		}
	}
}SegmentTree[maxn<<2];

struct nodes
{
	int l,r,val,lazy;
	void update(int x)
	{
		lazy^=x;
		if((r-l+1)&1) val^=x;
	}
}Tree[maxn<<2];

int lowbit(int x)
{
    return x&(-x);
}

int Query(int id)
{
    int ans=0;
    while(id)
    {
        ans^=c[id];
        id-=lowbit(id);
    }
    return ans;
}

void Update(int id,int x)
{
    while(id<=n)
    {
        c[id]^=x;
        id+=lowbit(id);
    }
}

void push_up(int id)
{
	//SegmentTree[id].init();
	for(int i=0;i<NUM;i++)
		SegmentTree[id].c[i]=SegmentTree[id<<1].c[i];
	for(int i=0;i<NUM;i++)
		SegmentTree[id].ins(SegmentTree[id<<1|1].c[i]);
}

void build(int id,int l,int r)
{
	SegmentTree[id].l=l;SegmentTree[id].r=r;SegmentTree[id].init();
	if(l==r)
	{
		SegmentTree[id].ins(a[l]);
		SegmentTree[id].val=a[l];
        Update(l,a[l]);
	}
	else
	{
		int mid=(l+r)>>1;
		build(id<<1,l,mid);
		build(id<<1|1,mid+1,r);
		push_up(id);
	}
}

void update(int id,int pos,int x)
{
	int L=SegmentTree[id].l,R=SegmentTree[id].r;
	if(L==R)
	{
		int val=SegmentTree[id].val;
		SegmentTree[id].init();
		SegmentTree[id].ins(x^val);
		SegmentTree[id].val=x^val;
		Update(pos,x);
		return;
	}
	int mid=(L+R)>>1;
	if(pos<=mid) update(id<<1,pos,x);
	else update(id<<1|1,pos,x);
	push_up(id);
}

node query(int id,int l,int r)
{
	int L=SegmentTree[id].l,R=SegmentTree[id].r;
	if(l<=L&&R<=r) return SegmentTree[id];
	int mid=(L+R)>>1;
	node ans;
	ans.init();
	if(l<=mid)
	{
		node res=query(id<<1,l,r);
		for(int i=0;i<NUM;i++)
			ans.ins(res.c[i]);
	}
	if(r>mid)
	{
		node res=query(id<<1|1,l,r);
		for(int i=0;i<NUM;i++)
			ans.ins(res.c[i]);
	}
	return ans;
}

int main()
{
    //freopen("587E.txt","r",stdin);
	pow_2[0]=1;
    for(int i=1;i<NUM-1;i++)
        pow_2[i]=2*pow_2[i-1];
	scanf("%d %d",&n,&q);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	for(int i=n;i>=1;i--)
		a[i]^=a[i-1];
	build(1,1,n);
	while(q--)
	{
		int op;
		scanf("%d",&op);
		if(op==1)
		{
			int l,r,k;
			scanf("%d %d %d",&l,&r,&k);
			update(1,l,k);
			if(r!=n)
                update(1,r+1,k);
		}
		else
		{
			int l,r;
			int ans=0;
			scanf("%d %d",&l,&r);
			node res;
			res.init();
			if(l<r)
                res=query(1,l+1,r);
            res.ins(Query(l));
            for(int i=0;i<NUM;i++)
                ans+=res.c[i]>0;
			printf("%d\n",pow_2[ans]);
		}
	}
	return 0;
}


#include <cstdio>
#include <cstring>
const int maxn=2e5+100;
const int NUM=32;
int n,q;
int a[maxn],c[maxn];
int pow_2[NUM-1];

struct node
{
	int c[NUM];
	int l,r,val;
	void init()
	{
		memset(c,0,sizeof(c));
	}
	void ins(int x)
	{
		for(int i=NUM-1;i>=0;i--)
		{
			if((x>>i)&1)
			{
				if(c[i])
					x^=c[i];
				else
				{
					c[i]=x;
					return;
				}
			}
		}
	}
}SegmentTree[maxn<<2];

struct nodes
{
	int l,r,val,lazy;
	void update(int x)
	{
		lazy^=x;
		if((r-l+1)&1) val^=x;
	}
}Tree[maxn<<2];

int lowbit(int x)
{
    return x&(-x);
}

int Query(int id)
{
    int ans=0;
    while(id)
    {
        ans^=c[id];
        id-=lowbit(id);
    }
    return ans;
}

void Update(int id,int x)
{
    while(id<=n)
    {
        c[id]^=x;
        id+=lowbit(id);
    }
}

void push_up(int id)
{
	SegmentTree[id].init();
	for(int i=0;i<NUM;i++)
	{
		SegmentTree[id].ins(SegmentTree[id<<1].c[i]);
		SegmentTree[id].ins(SegmentTree[id<<1|1].c[i]);
	}
}

void build(int id,int l,int r)
{
	SegmentTree[id].l=l;SegmentTree[id].r=r;SegmentTree[id].init();
	if(l==r)
	{
		SegmentTree[id].ins(a[l]);
		SegmentTree[id].val=a[l];
        Update(l,a[l]);
	}
	else
	{
		int mid=(l+r)>>1;
		build(id<<1,l,mid);
		build(id<<1|1,mid+1,r);
		push_up(id);
	}
}

void update(int id,int pos,int x)
{
	int L=SegmentTree[id].l,R=SegmentTree[id].r;
	if(L==R)
	{
		int val=SegmentTree[id].val;
		SegmentTree[id].init();
		SegmentTree[id].ins(x^val);
		SegmentTree[id].val=x^val;
		Update(pos,x);
		return;
	}
	int mid=(L+R)>>1;
	if(pos<=mid) update(id<<1,pos,x);
	else update(id<<1|1,pos,x);
	push_up(id);
}

node query(int id,int l,int r)
{
	int L=SegmentTree[id].l,R=SegmentTree[id].r;
	if(l<=L&&R<=r) return SegmentTree[id];
	int mid=(L+R)>>1;
	node ans;
	ans.init();
	if(l<=mid)
	{
		node res=query(id<<1,l,r);
		for(int i=0;i<NUM;i++)
			ans.ins(res.c[i]);
	}
	if(r>mid)
	{
		node res=query(id<<1|1,l,r);
		for(int i=0;i<NUM;i++)
			ans.ins(res.c[i]);
	}
	return ans;
}

int main()
{
    //freopen("587E.txt","r",stdin);
	pow_2[0]=1;
    for(int i=1;i<NUM-1;i++)
        pow_2[i]=2*pow_2[i-1];
	scanf("%d %d",&n,&q);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	for(int i=n;i>=1;i--)
		a[i]^=a[i-1];
	build(1,1,n);
	while(q--)
	{
		int op;
		scanf("%d",&op);
		if(op==1)
		{
			int l,r,k;
			scanf("%d %d %d",&l,&r,&k);
			update(1,l,k);
			if(r!=n)
                update(1,r+1,k);
		}
		else
		{
			int l,r;
			int ans=0;
			scanf("%d %d",&l,&r);
			node res;
			res.init();
			if(l<r)
                res=query(1,l+1,r);
            res.ins(Query(l));
            for(int i=0;i<NUM;i++)
                ans+=res.c[i]>0;
			printf("%d\n",pow_2[ans]);
		}
	}
	return 0;
}


#include <cstdio>
#include <cstring>
const int maxn=2e5+100;
const int NUM=30;
int n,q;
int a[maxn],c[maxn];
int pow_2[NUM];

struct node
{
	int c[NUM];
	int l,r,val;
	void init()
	{
		memset(c,0,sizeof(c));
	}
	void ins(int x)
	{
		if(!x) return;
		for(int i=NUM-1;i>=0;i--)
		{
			if((x>>i)&1)
			{
				if(c[i])
					x^=c[i];
				else
				{
					c[i]=x;
					return;
				}
			}
		}
	}
}SegmentTree[maxn<<2];

int lowbit(int x)
{
    return x&(-x);
}

int Query(int id)
{
    int ans=0;
    while(id)
    {
        ans^=c[id];
        id-=lowbit(id);
    }
    return ans;
}

void Update(int id,int x)
{
    while(id<=n)
    {
        c[id]^=x;
        id+=lowbit(id);
    }
}

void push_up(int id)
{
	//SegmentTree[id].init();
	for(int i=0;i<NUM;i++)
		SegmentTree[id].c[i]=SegmentTree[id<<1].c[i];
	for(int i=0;i<NUM;i++)
		SegmentTree[id].ins(SegmentTree[id<<1|1].c[i]);
}

void build(int id,int l,int r)
{
	SegmentTree[id].l=l;SegmentTree[id].r=r;SegmentTree[id].init();
	if(l==r)
	{
		SegmentTree[id].ins(a[l]);
		SegmentTree[id].val=a[l];
        Update(l,a[l]);
	}
	else
	{
		int mid=(l+r)>>1;
		build(id<<1,l,mid);
		build(id<<1|1,mid+1,r);
		push_up(id);
	}
}

void update(int id,int pos,int x)
{
	int L=SegmentTree[id].l,R=SegmentTree[id].r;
	if(L==R)
	{
		int val=SegmentTree[id].val;
		SegmentTree[id].init();
		SegmentTree[id].ins(x^val);
		SegmentTree[id].val=x^val;
		Update(pos,x);
		return;
	}
	int mid=(L+R)>>1;
	if(pos<=mid) update(id<<1,pos,x);
	else update(id<<1|1,pos,x);
	push_up(id);
}

node query(int id,int l,int r)
{
	int L=SegmentTree[id].l,R=SegmentTree[id].r;
	if(l<=L&&R<=r) return SegmentTree[id];
	int mid=(L+R)>>1;
	node ans;
	ans.init();
	if(l<=mid)
	{
		node res=query(id<<1,l,r);
		for(int i=0;i<NUM;i++)
			ans.ins(res.c[i]);
	}
	if(r>mid)
	{
		node res=query(id<<1|1,l,r);
		for(int i=0;i<NUM;i++)
			ans.ins(res.c[i]);
	}
	return ans;
}

int main()
{
    //freopen("587E.txt","r",stdin);
	pow_2[0]=1;
    for(int i=1;i<NUM;i++)
        pow_2[i]=2*pow_2[i-1];
	scanf("%d %d",&n,&q);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	for(int i=n;i>=1;i--)
		a[i]^=a[i-1];
	build(1,1,n);
	while(q--)
	{
		int op;
		scanf("%d",&op);
		if(op==1)
		{
			int l,r,k;
			scanf("%d %d %d",&l,&r,&k);
			update(1,l,k);
			if(r!=n)
                update(1,r+1,k);
		}
		else
		{
			int l,r;
			int ans=0;
			scanf("%d %d",&l,&r);
			node res;
			res.init();
			if(l<r)
                res=query(1,l+1,r);
            res.ins(Query(l));
            for(int i=0;i<NUM;i++)
                ans+=res.c[i]>0;
			printf("%d\n",pow_2[ans]);
		}
	}
	return 0;
}


#include <cstdio>
#include <cstring>
const int maxn=2e5+100;
const int NUM=30;
int n,q;
int a[maxn],c[maxn];
int pow_2[32];

struct node
{
	int c[NUM];
	int l,r,val;
	void init()
	{
		memset(c,0,sizeof(c));
	}
	void ins(int x)
	{
		if(!x) return;
		for(int i=NUM-1;i>=0;i--)
		{
			if((x>>i)&1)
			{
				if(c[i])
					x^=c[i];
				else
				{
					c[i]=x;
					return;
				}
			}
		}
	}
}SegmentTree[maxn<<2];

int lowbit(int x)
{
    return x&(-x);
}

int Query(int id)
{
    int ans=0;
    while(id)
    {
        ans^=c[id];
        id-=lowbit(id);
    }
    return ans;
}

void Update(int id,int x)
{
    while(id<=n)
    {
        c[id]^=x;
        id+=lowbit(id);
    }
}

void push_up(int id)
{
	//SegmentTree[id].init();
	for(int i=0;i<NUM;i++)
		SegmentTree[id].c[i]=SegmentTree[id<<1].c[i];
	for(int i=0;i<NUM;i++)
		SegmentTree[id].ins(SegmentTree[id<<1|1].c[i]);
}

void build(int id,int l,int r)
{
	SegmentTree[id].l=l;SegmentTree[id].r=r;SegmentTree[id].init();
	if(l==r)
	{
		SegmentTree[id].ins(a[l]);
		SegmentTree[id].val=a[l];
        Update(l,a[l]);
	}
	else
	{
		int mid=(l+r)>>1;
		build(id<<1,l,mid);
		build(id<<1|1,mid+1,r);
		push_up(id);
	}
}

void update(int id,int pos,int x)
{
	int L=SegmentTree[id].l,R=SegmentTree[id].r;
	if(L==R)
	{
		int val=SegmentTree[id].val;
		SegmentTree[id].init();
		SegmentTree[id].ins(x^val);
		SegmentTree[id].val=x^val;
		Update(pos,x);
		return;
	}
	int mid=(L+R)>>1;
	if(pos<=mid) update(id<<1,pos,x);
	else update(id<<1|1,pos,x);
	push_up(id);
}

node query(int id,int l,int r)
{
	int L=SegmentTree[id].l,R=SegmentTree[id].r;
	if(l<=L&&R<=r) return SegmentTree[id];
	int mid=(L+R)>>1;
	node ans;
	ans.init();
	if(l<=mid)
	{
		node res=query(id<<1,l,r);
		for(int i=0;i<NUM;i++)
			ans.c[i]=res.c[i];
	}
	if(r>mid)
	{
		node res=query(id<<1|1,l,r);
		for(int i=0;i<NUM;i++)
			ans.ins(res.c[i]);
	}
	return ans;
}

int main()
{
    //freopen("587E.txt","r",stdin);
	pow_2[0]=1;
    for(int i=1;i<32;i++)
        pow_2[i]=2*pow_2[i-1];
	scanf("%d %d",&n,&q);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	for(int i=n;i>=1;i--)
		a[i]^=a[i-1];
	build(1,1,n);
	while(q--)
	{
		int op;
		scanf("%d",&op);
		if(op==1)
		{
			int l,r,k;
			scanf("%d %d %d",&l,&r,&k);
			update(1,l,k);
			if(r!=n)
                update(1,r+1,k);
		}
		else
		{
			int l,r;
			int ans=0;
			scanf("%d %d",&l,&r);
			node res;
			res.init();
			if(l<r)
                res=query(1,l+1,r);
            res.ins(Query(l));
            for(int i=0;i<NUM;i++)
                ans+=res.c[i]>0;
			printf("%d\n",pow_2[ans]);
		}
	}
	return 0;
}


#include <cstdio>
#include <cstring>
const int maxn=2e5+100;
const int NUM=32;
int n,q;
int a[maxn],c[maxn];
int pow_2[NUM-1];

struct node
{
	int c[NUM];
	int l,r,val;
	void init()
	{
		memset(c,0,sizeof(c));
	}
	void ins(int x)
	{
		for(int i=NUM-1;i>=0;i--)
		{
			if((x>>i)&1)
			{
				if(c[i])
					x^=c[i];
				else
				{
					c[i]=x;
					return;
				}
			}
		}
	}
}SegmentTree[maxn<<2];

struct nodes
{
	int l,r,val,lazy;
	void update(int x)
	{
		lazy^=x;
		if((r-l+1)&1) val^=x;
	}
}Tree[maxn<<2];

int lowbit(int x)
{
    return x&(-x);
}

int Query(int id)
{
    int ans=0;
    while(id)
    {
        ans^=c[id];
        id-=lowbit(id);
    }
    return ans;
}

void Update(int id,int x)
{
    while(id<=n)
    {
        c[id]^=x;
        id+=lowbit(id);
    }
}

void push_up(int id)
{
	for(int i=0;i<NUM;i++)
	{
		SegmentTree[id].ins(SegmentTree[id<<1].c[i]);
		SegmentTree[id].ins(SegmentTree[id<<1|1].c[i]);
	}
}

void build(int id,int l,int r)
{
	SegmentTree[id].l=l;SegmentTree[id].r=r;SegmentTree[id].init();
	if(l==r)
	{
		SegmentTree[id].ins(a[l]);
		SegmentTree[id].val=a[l];
	}
	else
	{
		int mid=(l+r)>>1;
		build(id<<1,l,mid);
		build(id<<1|1,mid+1,r);
		push_up(id);
	}
}

void update(int id,int pos,int x)
{
	int L=SegmentTree[id].l,R=SegmentTree[id].r;
	if(L==R)
	{
		int val=SegmentTree[id].val;
		SegmentTree[id].init();
		SegmentTree[id].ins(x^val);
		SegmentTree[id].val=x^val;
		return;
	}
	int mid=(L+R)>>1;
	if(pos<=mid) update(id<<1,pos,x);
	else update(id<<1|1,pos,x);
	push_up(id);
}

node query(int id,int l,int r)
{
	int L=SegmentTree[id].l,R=SegmentTree[id].r;
	if(L==R) return SegmentTree[id];
	int mid=(L+R)>>1;
	node ans;
	ans.init();
	if(l<=mid)
	{
		node res=query(id<<1,l,r);
		for(int i=0;i<NUM;i++)
			ans.ins(res.c[i]);
	}
	if(r>mid)
	{
		node res=query(id<<1|1,l,r);
		for(int i=0;i<NUM;i++)
			ans.ins(res.c[i]);
	}
	return ans;
}

int main()
{
    //freopen("587E.txt","r",stdin);
	pow_2[0]=1;
    for(int i=1;i<NUM-1;i++)
        pow_2[i]=2*pow_2[i-1];
	scanf("%d %d",&n,&q);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	for(int i=n;i>=1;i--)
		a[i]^=a[i-1];
	build(1,1,n);
	for(int i=1;i<=n;i++)
        Update(i,a[i]);
	while(q--)
	{
		int op;
		scanf("%d",&op);
		if(op==1)
		{
			int l,r,k;
			scanf("%d %d %d",&l,&r,&k);
			update(1,l,k);
			Update(l,k);
			if(r!=n)
            {
                update(1,r+1,k);
                Update(r+1,k);
            }
		}
		else
		{
			int l,r;
			int ans=0;
			scanf("%d %d",&l,&r);
			node res;
			res.init();
			if(l<r)
                res=query(1,l+1,r);
            res.ins(Query(l));
            for(int i=0;i<NUM;i++)
                ans+=res.c[i]>0;
			printf("%d\n",pow_2[ans]);
		}
	}
	return 0;
}


#include <cstdio>
#include <cstring>
const int maxn=2e5+100;
const int NUM=30;
int n,q;
int a[maxn],c[maxn];
int pow_2[NUM-1];

struct node
{
	int c[NUM];
	int l,r,val;
	void init()
	{
		memset(c,0,sizeof(c));
	}
	void ins(int x)
	{
		if(!x) return;
		for(int i=NUM-1;i>=0;i--)
		{
			if((x>>i)&1)
			{
				if(c[i])
					x^=c[i];
				else
				{
					c[i]=x;
					return;
				}
			}
		}
	}
}SegmentTree[maxn<<2];

int lowbit(int x)
{
    return x&(-x);
}

int Query(int id)
{
    int ans=0;
    while(id)
    {
        ans^=c[id];
        id-=lowbit(id);
    }
    return ans;
}

void Update(int id,int x)
{
    while(id<=n)
    {
        c[id]^=x;
        id+=lowbit(id);
    }
}

void push_up(int id)
{
	//SegmentTree[id].init();
	for(int i=0;i<NUM;i++)
		SegmentTree[id].c[i]=SegmentTree[id<<1].c[i];
	for(int i=0;i<NUM;i++)
		SegmentTree[id].ins(SegmentTree[id<<1|1].c[i]);
}

void build(int id,int l,int r)
{
	SegmentTree[id].l=l;SegmentTree[id].r=r;SegmentTree[id].init();
	if(l==r)
	{
		SegmentTree[id].ins(a[l]);
		SegmentTree[id].val=a[l];
        Update(l,a[l]);
	}
	else
	{
		int mid=(l+r)>>1;
		build(id<<1,l,mid);
		build(id<<1|1,mid+1,r);
		push_up(id);
	}
}

void update(int id,int pos,int x)
{
	int L=SegmentTree[id].l,R=SegmentTree[id].r;
	if(L==R)
	{
		int val=SegmentTree[id].val;
		SegmentTree[id].init();
		SegmentTree[id].ins(x^val);
		SegmentTree[id].val=x^val;
		Update(pos,x);
		return;
	}
	int mid=(L+R)>>1;
	if(pos<=mid) update(id<<1,pos,x);
	else update(id<<1|1,pos,x);
	push_up(id);
}

node query(int id,int l,int r)
{
	int L=SegmentTree[id].l,R=SegmentTree[id].r;
	if(l<=L&&R<=r) return SegmentTree[id];
	int mid=(L+R)>>1;
	node ans;
	ans.init();
	if(l<=mid)
	{
		node res=query(id<<1,l,r);
		for(int i=0;i<NUM;i++)
			ans.ins(res.c[i]);
	}
	if(r>mid)
	{
		node res=query(id<<1|1,l,r);
		for(int i=0;i<NUM;i++)
			ans.ins(res.c[i]);
	}
	return ans;
}

int main()
{
    //freopen("587E.txt","r",stdin);
	pow_2[0]=1;
    for(int i=1;i<NUM;i++)
        pow_2[i]=2*pow_2[i-1];
	scanf("%d %d",&n,&q);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	for(int i=n;i>=1;i--)
		a[i]^=a[i-1];
	build(1,1,n);
	while(q--)
	{
		int op;
		scanf("%d",&op);
		if(op==1)
		{
			int l,r,k;
			scanf("%d %d %d",&l,&r,&k);
			update(1,l,k);
			if(r!=n)
                update(1,r+1,k);
		}
		else
		{
			int l,r;
			int ans=0;
			scanf("%d %d",&l,&r);
			node res;
			res.init();
			if(l<r)
                res=query(1,l+1,r);
            res.ins(Query(l));
            for(int i=0;i<NUM;i++)
                ans+=res.c[i]>0;
			printf("%d\n",pow_2[ans]);
		}
	}
	return 0;
}