#include <bits/stdc++.h>
using namespace std;
namespace fastIO{
	#define BUF_SIZE 100000
	#define OUT_SIZE 100000
	//fread->read
	bool IOerror=0;
//	inline char nc(){char ch=getchar();if(ch==-1)IOerror=1;return ch;}
	inline char nc(){
		static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
		if(p1==pend){
			p1=buf;pend=buf+fread(buf,1,BUF_SIZE,stdin);
			if(pend==p1){IOerror=1;return -1;}
		}
		return *p1++;
	}
	inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';}
	template<class T> inline bool read(T &x){
		bool sign=0;char ch=nc();x=0;
		for(;blank(ch);ch=nc());
		if(IOerror)return false;
		if(ch=='-')sign=1,ch=nc();
		for(;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
		if(sign)x=-x;
		return true;
	}
	inline bool read(double &x){
		bool sign=0;char ch=nc();x=0;
		for(;blank(ch);ch=nc());
		if(IOerror)return false;
		if(ch=='-')sign=1,ch=nc();
		for(;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
		if(ch=='.'){
			double tmp=1; ch=nc();
			for(;ch>='0'&&ch<='9';ch=nc())tmp/=10.0,x+=tmp*(ch-'0');
		}
		if(sign)x=-x;
		return true;
	}
	inline bool read(char *s){
		char ch=nc();
		for(;blank(ch);ch=nc());
		if(IOerror)return false;
		for(;!blank(ch)&&!IOerror;ch=nc())*s++=ch;
		*s=0;
		return true;
	}
	inline bool read(char &c){
		for(c=nc();blank(c);c=nc());
		if(IOerror){c=-1;return false;}
		return true;
	}
	template<class T,class... U>bool read(T& h,U&... t){return read(h)&&read(t...);}
	#undef OUT_SIZE
	#undef BUF_SIZE
};
using namespace fastIO;
/************* debug begin *************/
string to_string(string s){return '"'+s+'"';}
string to_string(const char* s){return to_string((string)s);}
string to_string(const bool& b){return(b?"true":"false");}
template<class T>string to_string(T x){ostringstream sout;sout<<x;return sout.str();}
template<class A,class B>string to_string(pair<A,B> p){return "("+to_string(p.first)+", "+to_string(p.second)+")";}
template<class A>string to_string(const vector<A> v){
	int f=1;string res="{";for(const auto x:v){if(!f)res+= ", ";f=0;res+=to_string(x);}res+="}";
	return res;
}
void debug_out(){puts("");}
template<class T,class... U>void debug_out(const T& h,const U&... t){cout<<" "<<to_string(h);debug_out(t...);}
#ifdef tokitsukaze
#define debug(...) cout<<"["<<#__VA_ARGS__<<"]:",debug_out(__VA_ARGS__);
#else
#define debug(...) 233;
#endif
/*************  debug end  *************/
#define mem(a,b) memset((a),(b),sizeof(a))
#define MP make_pair
#define pb push_back
#define fi first
#define se second
#define sz(x) (int)x.size()
#define all(x) x.begin(),x.end()
#define sqr(x) (x)*(x)
using namespace __gnu_cxx;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
typedef pair<int,ll> PIL;
typedef pair<ll,int> PLI;
typedef vector<int> VI;
typedef vector<ll> VL;
/************* define end  *************/
void println(VI x){for(int i=0;i<sz(x);i++) printf("%d%c",x[i]," \n"[i==sz(x)-1]);}
void println(VL x){for(int i=0;i<sz(x);i++) printf("%lld%c",x[i]," \n"[i==sz(x)-1]);}
template<class T> void read(T *x,int l,int r){for(int i=l;i<=r;i++) read(x[i]);}
void println(int *x,int l,int r){for(int i=l;i<=r;i++) printf("%d%c",x[i]," \n"[i==r]);}
void println(ll *x,int l,int r){for(int i=l;i<=r;i++) printf("%lld%c",x[i]," \n"[i==r]);}
/*************** IO end  ***************/
void go();
int main(){
	#ifdef tokitsukaze
		freopen("TEST.txt","r",stdin);
	#endif
	go();return 0;
}
const int INF=0x3f3f3f3f;
const ll LLINF=0x3f3f3f3f3f3f3f3fLL;
const double PI=acos(-1.0);
const double eps=1e-6;
const int MAX=2e5+5;
const ll mod=998244353;
/*********************************  head  *********************************/
struct Base
{
	#define type int
	#define mx 31
	type d[mx],p[mx],cnt;
	void init()
	{
		memset(d,0,sizeof(d));
		memset(p,0,sizeof(p));
		cnt=0;
	}
	bool insert(type x)
	{
		int i;
		for(i=mx;~i;i--)
		{
			if(!(x&(1LL<<i))) continue;
			if(!d[i])
			{
				cnt++;
				d[i]=x;
				break;
			}
			x^=d[i];
		}
		return x>0;
	}
	void merge(Base x)
	{
		for(int i=mx;~i;i--)
		{
			if(x.d[i]) insert(x.d[i]);
		}
	}
};
struct Segment_Tree
{
	#define type int
	#define ls (id<<1)
	#define rs (id<<1|1)
	int n,ql,qr;
	type tag[MAX<<2],qv,pos[MAX];
	Base v[MAX<<2];
	void pushup(int id)
	{
		v[id]=v[ls];
		v[id].merge(v[rs]);
	}
	void pushdown(int id)
	{
		if(!tag[id]) return;
		tag[ls]^=tag[id];
		tag[rs]^=tag[id];
		v[ls].insert(tag[id]);
		v[rs].insert(tag[id]);
		tag[id]=0;
	}
	void initpos(int l,int r,int id)
	{
		if(l==r)
		{
			pos[l]=id;
			return;
		}
		int mid=(l+r)>>1;
		initpos(l,mid,ls);
		initpos(mid+1,r,rs);
	}
	void build(int l,int r,int id)
	{
		tag[id]=0;
		if(l==r) return;
		v[id].init();
		int mid=(l+r)>>1;
		build(l,mid,ls);
		build(mid+1,r,rs);
		pushup(id);
	}
	void update(int l,int r,int id)
	{
		if(l>=ql&&r<=qr)
		{
			tag[id]^=qv;
			v[id].insert(qv);
			return;
		}
		pushdown(id);
		int mid=(l+r)>>1;
		if(ql<=mid) update(l,mid,ls);
		if(qr>mid) update(mid+1,r,rs);
		pushup(id);
	}
	Base query(int l,int r,int id)
	{
		Base res;
		res.init();
		if(l>=ql&&r<=qr) return v[id];
		pushdown(id);
		int mid=(l+r)>>1;
		if(ql<=mid) res=query(l,mid,ls);
		if(qr>mid) res.merge(query(mid+1,r,rs));
		return res;
	}
	void build(int _n){n=_n;build(1,n,1);}
	void initpos(int _n){n=_n;initpos(1,n,1);}
	void upd(int l,int r,type v)
	{
		ql=l;
		qr=r;
		qv=v;
		update(1,n,1);
	}
	Base ask(int l,int r)
	{
		ql=l;
		qr=r;
		return query(1,n,1);
	}
	#undef type
	#undef ls
	#undef rs
}tr;
void go()
{
	int n,q,i,x,op,l,r;
	while(read(n,q))
	{
		tr.initpos(n);
		for(i=1;i<=n;i++)
		{
			read(x);
			tr.v[tr.pos[i]].init();
			tr.v[tr.pos[i]].insert(x);
		}
		tr.build(n);
		while(q--)
		{
			read(op,l,r);
			if(op==1)
			{
				read(x);
				tr.upd(l,r,x);
			}
			else
			{
				if(l==r) puts("1");
				else printf("%lld\n",1LL<<tr.ask(l,r).cnt);
			}
		}
	}
}


#include <bits/stdc++.h>
using namespace std;
namespace fastIO{
	#define BUF_SIZE 100000
	#define OUT_SIZE 100000
	//fread->read
	bool IOerror=0;
//	inline char nc(){char ch=getchar();if(ch==-1)IOerror=1;return ch;}
	inline char nc(){
		static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
		if(p1==pend){
			p1=buf;pend=buf+fread(buf,1,BUF_SIZE,stdin);
			if(pend==p1){IOerror=1;return -1;}
		}
		return *p1++;
	}
	inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';}
	template<class T> inline bool read(T &x){
		bool sign=0;char ch=nc();x=0;
		for(;blank(ch);ch=nc());
		if(IOerror)return false;
		if(ch=='-')sign=1,ch=nc();
		for(;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
		if(sign)x=-x;
		return true;
	}
	inline bool read(double &x){
		bool sign=0;char ch=nc();x=0;
		for(;blank(ch);ch=nc());
		if(IOerror)return false;
		if(ch=='-')sign=1,ch=nc();
		for(;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
		if(ch=='.'){
			double tmp=1; ch=nc();
			for(;ch>='0'&&ch<='9';ch=nc())tmp/=10.0,x+=tmp*(ch-'0');
		}
		if(sign)x=-x;
		return true;
	}
	inline bool read(char *s){
		char ch=nc();
		for(;blank(ch);ch=nc());
		if(IOerror)return false;
		for(;!blank(ch)&&!IOerror;ch=nc())*s++=ch;
		*s=0;
		return true;
	}
	inline bool read(char &c){
		for(c=nc();blank(c);c=nc());
		if(IOerror){c=-1;return false;}
		return true;
	}
	template<class T,class... U>bool read(T& h,U&... t){return read(h)&&read(t...);}
	#undef OUT_SIZE
	#undef BUF_SIZE
};
using namespace fastIO;
/************* debug begin *************/
string to_string(string s){return '"'+s+'"';}
string to_string(const char* s){return to_string((string)s);}
string to_string(const bool& b){return(b?"true":"false");}
template<class T>string to_string(T x){ostringstream sout;sout<<x;return sout.str();}
template<class A,class B>string to_string(pair<A,B> p){return "("+to_string(p.first)+", "+to_string(p.second)+")";}
template<class A>string to_string(const vector<A> v){
	int f=1;string res="{";for(const auto x:v){if(!f)res+= ", ";f=0;res+=to_string(x);}res+="}";
	return res;
}
void debug_out(){puts("");}
template<class T,class... U>void debug_out(const T& h,const U&... t){cout<<" "<<to_string(h);debug_out(t...);}
#ifdef tokitsukaze
#define debug(...) cout<<"["<<#__VA_ARGS__<<"]:",debug_out(__VA_ARGS__);
#else
#define debug(...) 233;
#endif
/*************  debug end  *************/
#define mem(a,b) memset((a),(b),sizeof(a))
#define MP make_pair
#define pb push_back
#define fi first
#define se second
#define sz(x) (int)x.size()
#define all(x) x.begin(),x.end()
#define sqr(x) (x)*(x)
using namespace __gnu_cxx;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
typedef pair<int,ll> PIL;
typedef pair<ll,int> PLI;
typedef vector<int> VI;
typedef vector<ll> VL;
/************* define end  *************/
void println(VI x){for(int i=0;i<sz(x);i++) printf("%d%c",x[i]," \n"[i==sz(x)-1]);}
void println(VL x){for(int i=0;i<sz(x);i++) printf("%lld%c",x[i]," \n"[i==sz(x)-1]);}
template<class T> void read(T *x,int l,int r){for(int i=l;i<=r;i++) read(x[i]);}
void println(int *x,int l,int r){for(int i=l;i<=r;i++) printf("%d%c",x[i]," \n"[i==r]);}
void println(ll *x,int l,int r){for(int i=l;i<=r;i++) printf("%lld%c",x[i]," \n"[i==r]);}
/*************** IO end  ***************/
void go();
int main(){
	#ifdef tokitsukaze
		freopen("TEST.txt","r",stdin);
	#endif
	go();return 0;
}
const int INF=0x3f3f3f3f;
const ll LLINF=0x3f3f3f3f3f3f3f3fLL;
const double PI=acos(-1.0);
const double eps=1e-6;
const int MAX=2e5+10;
const ll mod=998244353;
/*********************************  head  *********************************/
struct Fenwick_Tree
{
	#define type int
	type bit[MAX];
	int n;
	void init(int _n){n=_n;mem(bit,0);}
	int lowbit(int x){return x&(-x);}
	void insert(int x,type v)
	{
		while(x<=n)
		{
			bit[x]^=v;
			x+=lowbit(x);
		}
	}
	type get(int x)
	{
		type res=0;
		while(x)
		{
			res^=bit[x];
			x-=lowbit(x);
		}
		return res;
	}
	type query(int l,int r)
	{
		return get(r)^get(l-1);
	}
	#undef type
}bit;
struct Base
{
	#define type int
	#define mx 31
	type d[mx+3],cnt;
	Base()
	{
		memset(d,0,sizeof(d));
		cnt=0;
	}
	void init()
	{
		memset(d,0,sizeof(d));
		cnt=0;
	}
	bool insert(type x)
	{
		int i;
		for(i=mx;~i;i--)
		{
			if(!(x&(1LL<<i))) continue;
			if(!d[i])
			{
				cnt++;
				d[i]=x;
				break;
			}
			x^=d[i];
		}
		return x>0;
	}
	void merge(Base x)
	{
		if(cnt<x.cnt)
		{
			swap(cnt,x.cnt);
			swap(d,x.d);
		}
		for(int i=mx;~i;i--)
		{
			if(x.d[i]) insert(x.d[i]);
		}
	}
};
struct Segment_Tree
{
	#define type int
	#define ls (id<<1)
	#define rs (id<<1|1)
	int n,ql,qr;
	type a[MAX],qv;
	Base v[MAX<<2];
	void pushup(int id)
	{
		v[id]=v[ls];
		v[id].merge(v[rs]);
	}
	void build(int l,int r,int id)
	{
		v[id].init();
		if(l==r)
		{
			v[id].insert(a[l]);
			return;
		}
		int mid=(l+r)>>1;
		build(l,mid,ls);
		build(mid+1,r,rs);
		pushup(id);
	}
	void update(int l,int r,int id)
	{
		if(l==r&&l==ql)
		{
			v[id].init();
			a[l]^=qv;
			v[id].insert(a[l]);
			return;
		}
		int mid=(l+r)>>1;
		if(ql<=mid) update(l,mid,ls);
		if(qr>mid) update(mid+1,r,rs);
		pushup(id);
	}
	Base res;
	void query(int l,int r,int id)
	{
		if(l>=ql&&r<=qr)
		{
			res.merge(v[id]);
			return;
		}
		int mid=(l+r)>>1;
		if(ql<=mid) query(l,mid,ls);
		if(qr>mid) query(mid+1,r,rs);
	}
	void build(int _n){n=_n;build(1,n,1);}
	void upd(int l,int r,type v)
	{
		ql=l;
		qr=r;
		qv=v;
		update(1,n,1);
	}
	Base ask(int l,int r)
	{
		if(l>r) return Base();
		ql=l;
		qr=r;
		res.init();
		query(1,n,1);
		return res;
	}
	#undef type
	#undef ls
	#undef rs
}tr;
int a[MAX];
void go()
{
	int n,q,i,op,l,r,x;
	while(read(n,q))
	{
		bit.init(n+1);
		for(i=1;i<=n;i++) read(a[i]);
		for(i=1;i<n;i++) tr.a[i]=a[i]^a[i+1];
		if(n>1) tr.build(n-1);
		while(q--)
		{
			read(op,l,r);
			if(op==1)
			{
				read(x);
				if(l>1) tr.upd(l-1,l-1,x);
				if(r<n) tr.upd(r,r,x);
				bit.insert(l,x);
				bit.insert(r+1,x);
			}
			else
			{
				Base res=tr.ask(l,r-1);
				res.insert(bit.get(l)^a[l]);
				printf("%lld\n",1LL<<res.cnt);
			}
		}
	}
}


#include <bits/stdc++.h>
using namespace std;
int fw[200005], n;
void upd(int idx,int v){
	++idx;
	while(idx<=n){
		fw[idx]^=v;
		idx+=idx&-idx;
	}
}
int get(int idx){
	++idx; int v=0;
	while(idx){
		v^=fw[idx];
		idx-=idx&-idx;
	}
	return v;
}
int N;
vector<int>t[2<<18];
void insert(vector<int>&c,int x){
	for(int &b:c) x=min(x,x^b);
	if(!x) return;
	for(int &b:c) b=min(b,b^x);
	c.emplace_back(x);
}
vector<int>operator+(vector<int>a,vector<int>b){
	for(int x:b) insert(a,x);
	return a;
}
void update(int p,int k){
	p+=N;
	t[p][0]^=k;
	for(p>>=1;p>0;p>>=1)
		t[p] = t[p<<1|0] + t[p<<1|1];
}
vector<int> query(int l,int r){
	vector<int>re;
	l+=N; r+=N;
	for(;l<r;l>>=1,r>>=1){
		if(l&1) re=re + t[l++];
		if(r&1) re=re + t[--r];
	}
	return re;
}
int main(){
	int q, qt, l, r, k, x=0, y;
	scanf("%d %d",&n,&q);
	for(N=n;N&(N-1);N+=N&-N);
	for(int i=0;i<n;++i) {
		scanf("%d",&y);
		upd(i,y^x);
		t[N+i]={y^x};
		x=y;
	}
	for(int i=N-1;i>0;--i) {
		t[i]=t[i<<1|0] + t[i<<1|1];
	}
	while(q--){
		scanf("%d %d %d",&qt,&l,&r); --l; --r;
		if(qt==1){
			scanf("%d",&k);
			upd(l,k); upd(r+1,k);
			update(l,k);
			if(r+1<n) update(r+1,k);
		}else{
			vector<int>re = query(l+1,r+1);
			re = re + vector<int>{get(l)};
			printf("%u\n",1<<re.size());
		}
	}
	return 0;
}


//satyaki3794
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <cassert>
#include <cstring>
#include <cmath>
#define ff first
#define ss second
#define pb push_back
#define MOD (1000000007LL)
#define LEFT(n) (2*(n))
#define RIGHT(n) (2*(n)+1)

using namespace std;
typedef long long ll;
typedef pair<int, int> ii;
typedef pair<int, ii> iii;

ll pwr(ll base, ll p, ll mod = MOD){
ll ans = 1;while(p){if(p&1)ans=(ans*base)%mod;base=(base*base)%mod;p/=2;}return ans;
}

int n, arr[200005], tree[800005], lazy[800005];

void build(int node, int s, int e){
    if(s > e)   return;
    if(s == e){
        tree[node] = arr[s];
        return;
    }
    int mid = (s+e)/2;
    build(LEFT(node), s, mid);
    build(RIGHT(node), mid+1, e);
    tree[node] = tree[LEFT(node)] ^ tree[RIGHT(node)];
}

void update(int node, int s, int e, int lo, int hi, int val){
    if(s > e)   return;
    if(lazy[node] != 0){
        tree[node] ^= lazy[node];
        if(s != e){
            lazy[LEFT(node)] ^= lazy[node];
            lazy[RIGHT(node)] ^= lazy[node];
        }
        lazy[node] = 0;
    }
    if(lo > e || s > hi)    return;
    if(s >= lo && e <= hi){
        tree[node] ^= val;
        if(s != e){
            lazy[LEFT(node)] ^= val;
            lazy[RIGHT(node)] ^= val;
        }
        return;
    }
    int mid = (s+e)/2;
    update(LEFT(node), s, mid, lo, hi, val);
    update(RIGHT(node), mid+1, e, lo, hi, val);
    tree[node] = tree[LEFT(node)] ^ tree[RIGHT(node)];
}

int query(int node, int s, int e, int pos){
    if(s > e)   return 0;
    if(lazy[node] != 0){
        tree[node] ^= lazy[node];
        if(s != e){
            lazy[LEFT(node)] ^= lazy[node];
            lazy[RIGHT(node)] ^= lazy[node];
        }
        lazy[node] = 0;
    }
    if(pos > e || s > pos)    return 0;
    if(s == e)  return tree[node];
    int mid = (s+e)/2;
    int a = query(LEFT(node), s, mid, pos);
    int b = query(RIGHT(node), mid+1, e, pos);
    return a^b;
}

void insert(vector<int> &v, int val){
    for(int i=0;i<(int)v.size();i++)
        val = min(val, val ^ v[i]);
    if(val > 0)
        v.pb(val);
}

vector<int> tree2[800005];

void build2(int node, int s, int e){
    if(s > e)   return;
    if(s == e){
        if(arr[s] > 0)
            tree2[node].pb(arr[s]);
        return;
    }
    int mid = (s+e)/2;
    build2(LEFT(node), s, mid);
    build2(RIGHT(node), mid+1, e);
    tree2[node] = tree2[LEFT(node)];
    for(int k=0;k<(int)tree2[RIGHT(node)].size();k++)
        insert(tree2[node], tree2[RIGHT(node)][k]);
}

void update2(int node, int s, int e, int pos, int val){
    if(s > e || pos > e || s > pos)   return;
    if(s == e){
        int last = 0;
        if(!tree2[node].empty())
            last = tree2[node][0];
        tree2[node].clear();
        if((last^val) > 0)
            tree2[node].pb(last^val);
        return;
    }
    int mid = (s+e)/2;
    update2(LEFT(node), s, mid, pos, val);
    update2(RIGHT(node), mid+1, e, pos, val);
    tree2[node] = tree2[LEFT(node)];
    for(int k=0;k<(int)tree2[RIGHT(node)].size();k++)
        insert(tree2[node], tree2[RIGHT(node)][k]);
}

vector<int> query2(int node, int s, int e, int lo, int hi){
    if(s > e || lo > e || s > hi)   return vector<int> (0);
    if(s >= lo && e <= hi)  return tree2[node];
    int mid = (s+e)/2;
    vector<int> a = query2(LEFT(node), s, mid, lo, hi);
    vector<int> b = query2(RIGHT(node), mid+1, e, lo, hi);
    for(int k=0;k<(int)b.size();k++)
        insert(a, b[k]);
    return a;
}

int main(){

    // ios_base::sync_with_stdio(0);
    // freopen("input.txt", "r", stdin);

    int q;
    scanf("%d%d", &n, &q);
    for(int i=1;i<=n;i++){
        scanf("%d", &arr[i]);
    }
    build(1, 1, n);

    for(int i=n;i>=2;i--){
        arr[i] ^= arr[i-1];
    }
    build2(1, 1, n);

// cout<<"arr: ";for(int i=1;i<=n;i++) cout<<arr[i]<<" ";cout<<endl;

    while(q--){

        int op;
        scanf("%d", &op);

        if(op == 1){

            int l, r, val;
            scanf("%d%d%d", &l, &r, &val);
            update(1, 1, n, l, r, val);
            update2(1, 1, n, l, val);
            update2(1, 1, n, r+1, val);
        }
        else{

            int l, r;
            scanf("%d%d", &l, &r);

            int firstval = query(1, 1, n, l);
// cout<<l<<" "<<r<<" "<<firstval<<endl;
            if(l == r){
                if(firstval == 0)   printf("1\n");
                else    printf("2\n");
            }
            else{
                vector<int> ans = query2(1, 1, n, l+1, r);
// cout<<"ans: ";for(int i=0;i<(int)ans.size();i++)    cout<<ans[i]<<" ";cout<<endl;
                insert(ans, firstval);
                printf("%d\n", (1<<(int)ans.size()));
            }
        }
    }

    return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int N = 200050;

struct _Bas{
	int bas[30], siz, tg;
	_Bas(){
		siz = tg = 0;
		memset(bas, 0, sizeof(bas));
	}
	void insert(int num){
		for(int i = 29; i >= 0; i --){
			if(num == 0)break;
			if((num & (1 << i)) == 0)
				continue;
			if(bas[i] == 0){
				bas[i] = num;
				siz ++; break;
			}
			num ^= bas[i];
		}
	}
	_Bas operator + (const _Bas &b)const{
		_Bas ret; ret.tg = tg;
		for(int i = 0; i <= 29; i ++){
			if(bas[i])ret.insert(bas[i]);
			if(b.bas[i])ret.insert(b.bas[i]);
		}
		ret.insert(tg ^ b.tg);
		return ret;
	}
}B[4 * N], ans;

#define lc (p << 1)
#define rc (p << 1|1)
int tg[4 * N], a[N], n, m;
void paint(int p, int num){
	tg[p] ^= num;
	B[p].tg ^= num;
}
void tagdown(int p){
	if(tg[p] > 0){
		paint(lc, tg[p]);
		paint(rc, tg[p]);
		tg[p] = 0;
	}
}
void build(int p, int l, int r){
	if(l == r){
		B[p].tg = a[l];
		return;
	}
	int md = l + r >> 1;
	build(lc, l, md);
	build(rc, md + 1, r);
	B[p] = B[lc] + B[rc];
}
void _XOR(int p, int l, int r, int x, int y, int num){
	if(l == x && r == y){
		paint(p, num);
		return;
	}
	int md = l + r >> 1; tagdown(p);
	if(y <= md)_XOR(lc, l, md, x, y, num);
	else if(x > md)_XOR(rc, md + 1, r, x, y, num);
	else{
		_XOR(lc, l, md, x, md, num);
		_XOR(rc, md + 1, r, md + 1, y, num);
	}
	B[p] = B[lc] + B[rc];
}
void query(int p, int l, int r, int x, int y){
	if(l == x && r == y){
		ans = ans + B[p];
		return;
	}
	int md = l + r >> 1; tagdown(p);
	if(y <= md)query(lc, l, md, x, y);
	else if(x > md)query(rc, md + 1, r, x, y);
	else{
		query(lc, l, md, x, md);
		query(rc, md + 1, r, md + 1, y);
	}
	B[p] = B[lc] + B[rc];
}

int main()
{
	int i, j, k, h;
	scanf("%d%d", &n, &m);
	for(i = 1; i <= n; i ++)
		scanf("%d", &a[i]);
	build(1, 1, n);
	for(i = 1; i <= m; i ++){
		scanf("%d", &j);
		if(j == 1){
			scanf("%d%d%d", &j, &k, &h);
			_XOR(1, 1, n, j, k, h);
		}else{
			scanf("%d%d", &j, &k);
			ans = _Bas(), query(1, 1, n, j, k);
			printf("%d\n", 1 << ans.siz);
		}
	}

	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int N = 200050;

struct _Bas{
	int bas[30], siz, tg;
	_Bas(){
		siz = tg = 0;
		memset(bas, 0, sizeof(bas));
	}
	void insert(int num){
		for(int i = 29; i >= 0; i --){
			if(num == 0)break;
			if((num & (1 << i)) == 0)
				continue;
			if(bas[i] == 0){
				bas[i] = num;
				siz ++; break;
			}
			num ^= bas[i];
		}
	}
	_Bas operator + (const _Bas &b)const{
		_Bas ret; ret.tg = tg;
		for(int i = 0; i <= 29; i ++){
			if(bas[i])ret.insert(bas[i]);
			if(b.bas[i])ret.insert(b.bas[i]);
		}
		ret.insert(tg ^ b.tg);
		return ret;
	}
}B[4 * N], ans;

#define lc (p << 1)
#define rc (p << 1|1)
int tg[4 * N], a[N], n, m;
void paint(int p, int num){
	tg[p] ^= num;
	B[p].tg ^= num;
}
void tagdown(int p){
	if(tg[p] > 0){
		paint(lc, tg[p]);
		paint(rc, tg[p]);
		tg[p] = 0;
	}
}
void build(int p, int l, int r){
	if(l == r){
		B[p].tg = a[l];
		return;
	}
	int md = l + r >> 1;
	build(lc, l, md);
	build(rc, md + 1, r);
	B[p] = B[lc] + B[rc];
}
void _XOR(int p, int l, int r, int x, int y, int num){
	if(l == x && r == y){
		paint(p, num);
		return;
	}
	int md = l + r >> 1; tagdown(p);
	if(y <= md)_XOR(lc, l, md, x, y, num);
	else if(x > md)_XOR(rc, md + 1, r, x, y, num);
	else{
		_XOR(lc, l, md, x, md, num);
		_XOR(rc, md + 1, r, md + 1, y, num);
	}
	B[p] = B[lc] + B[rc];
}
void query(int p, int l, int r, int x, int y){
	if(l == x && r == y){
		ans = ans + B[p];
		return;
	}
	int md = l + r >> 1; tagdown(p);
	if(y <= md)query(lc, l, md, x, y);
	else if(x > md)query(rc, md + 1, r, x, y);
	else{
		query(lc, l, md, x, md);
		query(rc, md + 1, r, md + 1, y);
	}
	B[p] = B[lc] + B[rc];
}
namespace io{
	const int L = (1 << 19)+1;
	char ibuf[L], *iS, *iT, obuf[L], *oS = obuf, *oT = obuf + L - 1, c, st[55]; int f, tp;
	inline char gc(){
		if(iS == iT){
			iT = (iS = ibuf) + fread(ibuf, 1, L, stdin);
			return iS == iT ? EOF : *iS ++;
		}
		return *iS ++;
	}
	inline void cbuf(){fwrite(obuf, 1, oS - obuf, stdout); oS = obuf;}
	inline void putc(char x){*oS ++ = x; if(oS == oT)cbuf();}
	template<class I>void gi(I &x){
		for(f = 1,c = gc(); c < '0' || c > '9'; c = gc())if(c == '-')f = -1;
		for(x = 0; c <= '9'&&c >= '0'; c = gc())x = x * 10 + (c & 15); x *= f;
	}
	template<class T>void print(T x){
		if(x == 0)putc('0'); if(x < 0)putc('-'), x = -x;
		while(x)st[++ tp]= x % 10 + '0',x /= 10;
		while(tp)putc(st[tp --]);
		putc('\n');
	}
};
using io :: print;
using io :: gi;

int main()
{
	int i, j, k, h;
	gi(n), gi(m);
	for(i = 1; i <= n; i ++)
		gi(a[i]);
	build(1, 1, n);
	for(i = 1; i <= m; i ++){
		gi(j);
		if(j == 1){
			gi(j), gi(k), gi(h);
			_XOR(1, 1, n, j, k, h);
		}else{
			gi(j), gi(k);
			ans = _Bas(), query(1, 1, n, j, k);
			print(1 << ans.siz);
		}
	}
	io :: cbuf();

	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int N = 200050;

struct _Bas{
	int bas[30], siz, tg;
	_Bas(){
		siz = tg = 0;
		memset(bas, 0, sizeof(bas));
	}
	void insert(int num){
		if(siz == 30)return;
		for(int i = 29; i >= 0; i --){
			if((num & (1 << i)) == 0)
				continue;
			if(bas[i] == 0){
				bas[i] = num;
				siz ++; break;
			}
			num ^= bas[i];
		}
	}
	_Bas operator + (const _Bas &b)const{
		_Bas ret;
		if(siz >= b.siz){
			ret = *this;
			for(int i = 0; i <= 29; i ++)
				if(b.bas[i])ret.insert(b.bas[i]);
		}else{
			ret = b;
			for(int i = 0; i <= 29; i ++)
				if(bas[i])ret.insert(bas[i]);
		}
		ret.insert(tg ^ b.tg);
		return ret;
	}
}B[4 * N], ans;

#define lc (p << 1)
#define rc (p << 1|1)
int tg[4 * N], a[N], n, m;
void paint(int p, int num){
	tg[p] ^= num;
	B[p].tg ^= num;
}
void tagdown(int p){
	if(tg[p] > 0){
		paint(lc, tg[p]);
		paint(rc, tg[p]);
		tg[p] = 0;
	}
}
void build(int p, int l, int r){
	if(l == r){
		B[p].tg = a[l];
		return;
	}
	int md = l + r >> 1;
	build(lc, l, md);
	build(rc, md + 1, r);
	B[p] = B[lc] + B[rc];
}
void _XOR(int p, int l, int r, int x, int y, int num){
	if(l == x && r == y){
		paint(p, num);
		return;
	}
	int md = l + r >> 1; tagdown(p);
	if(y <= md)_XOR(lc, l, md, x, y, num);
	else if(x > md)_XOR(rc, md + 1, r, x, y, num);
	else{
		_XOR(lc, l, md, x, md, num);
		_XOR(rc, md + 1, r, md + 1, y, num);
	}
	B[p] = B[lc] + B[rc];
}
void query(int p, int l, int r, int x, int y){
	if(ans.siz == 30)return;
	if(l == x && r == y){
		ans = ans + B[p];
		return;
	}
	int md = l + r >> 1; tagdown(p);
	if(y <= md)query(lc, l, md, x, y);
	else if(x > md)query(rc, md + 1, r, x, y);
	else{
		query(lc, l, md, x, md);
		query(rc, md + 1, r, md + 1, y);
	}
	B[p] = B[lc] + B[rc];
}
namespace io{
	const int L = (1 << 19)+1;
	char ibuf[L], *iS, *iT, obuf[L], *oS = obuf, *oT = obuf + L - 1, c, st[55]; int f, tp;
	inline char gc(){
		if(iS == iT){
			iT = (iS = ibuf) + fread(ibuf, 1, L, stdin);
			return iS == iT ? EOF : *iS ++;
		}
		return *iS ++;
	}
	inline void cbuf(){fwrite(obuf, 1, oS - obuf, stdout); oS = obuf;}
	inline void putc(char x){*oS ++ = x; if(oS == oT)cbuf();}
	template<class I>void gi(I &x){
		for(f = 1,c = gc(); c < '0' || c > '9'; c = gc())if(c == '-')f = -1;
		for(x = 0; c <= '9'&&c >= '0'; c = gc())x = x * 10 + (c & 15); x *= f;
	}
	template<class T>void print(T x){
		if(x == 0)putc('0'); if(x < 0)putc('-'), x = -x;
		while(x)st[++ tp]= x % 10 + '0',x /= 10;
		while(tp)putc(st[tp --]);
		putc('\n');
	}
};
using io :: print;
using io :: gi;

int main()
{
	int i, j, k, h;
	gi(n), gi(m);
	for(i = 1; i <= n; i ++)
		gi(a[i]);
	build(1, 1, n);
	for(i = 1; i <= m; i ++){
		gi(j);
		if(j == 1){
			gi(j), gi(k), gi(h);
			_XOR(1, 1, n, j, k, h);
		}else{
			gi(j), gi(k);
			ans = _Bas(), query(1, 1, n, j, k);
			print(1 << ans.siz);
		}
	}
	io :: cbuf();

	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int N = 200050;

struct _Bas{
	int bas[30], siz, tg;
	_Bas(){
		siz = tg = 0;
		memset(bas, 0, sizeof(bas));
	}
	void insert(int num){
		for(int i = 29; i >= 0; i --){
			if((num & (1 << i)) == 0)
				continue;
			if(bas[i] == 0){
				bas[i] = num;
				siz ++; break;
			}
			num ^= bas[i];
		}
	}
	_Bas operator + (const _Bas &b)const{
		_Bas ret; ret.tg = tg;
		for(int i = 0; i <= 29; i ++){
			if(bas[i])ret.insert(bas[i]);
			if(b.bas[i])ret.insert(b.bas[i]);
		}
		ret.insert(tg ^ b.tg);
		return ret;
	}
}B[4 * N], ans;

#define lc (p << 1)
#define rc (p << 1|1)
int tg[4 * N], a[N], n, m;
void paint(int p, int num){
	tg[p] ^= num;
	B[p].tg ^= num;
}
void tagdown(int p){
	if(tg[p] > 0){
		paint(lc, tg[p]);
		paint(rc, tg[p]);
		tg[p] = 0;
	}
}
void build(int p, int l, int r){
	if(l == r){
		B[p].tg = a[l];
		return;
	}
	int md = l + r >> 1;
	build(lc, l, md);
	build(rc, md + 1, r);
	B[p] = B[lc] + B[rc];
}
void _XOR(int p, int l, int r, int x, int y, int num){
	if(l == x && r == y){
		paint(p, num);
		return;
	}
	int md = l + r >> 1; tagdown(p);
	if(y <= md)_XOR(lc, l, md, x, y, num);
	else if(x > md)_XOR(rc, md + 1, r, x, y, num);
	else{
		_XOR(lc, l, md, x, md, num);
		_XOR(rc, md + 1, r, md + 1, y, num);
	}
	B[p] = B[lc] + B[rc];
}
void query(int p, int l, int r, int x, int y){
	if(l == x && r == y){
		ans = ans + B[p];
		return;
	}
	int md = l + r >> 1; tagdown(p);
	if(y <= md)query(lc, l, md, x, y);
	else if(x > md)query(rc, md + 1, r, x, y);
	else{
		query(lc, l, md, x, md);
		query(rc, md + 1, r, md + 1, y);
	}
	B[p] = B[lc] + B[rc];
}

int main()
{

	int i, j, k, h;
	scanf("%d%d", &n, &m);
	for(i = 1; i <= n; i ++)
		scanf("%d", &a[i]);
	build(1, 1, n);
	for(i = 1; i <= m; i ++){
		scanf("%d", &j);
		if(j == 1){
			scanf("%d%d%d", &j, &k, &h);
			_XOR(1, 1, n, j, k, h);
		}else{
			scanf("%d%d", &j, &k);
			ans = _Bas(), query(1, 1, n, j, k);
			int tmp = 1 << ans.siz;
			if(ans.tg){
				for(j = 29; j >= 0; j --)
					if(ans.tg & (1 << j))
						ans.tg ^= ans.bas[j];
				if(ans.tg == 0)tmp --;
			}
			printf("%d\n", tmp);
		}
	}

	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define fi first
#define se second
#define pb push_back
#define mp make_pair

typedef pair<int, int> ii;

const int N = 2e5 + 5;

int n, q, a[N];

struct IT {
    int lz[4 * N];
    vector<int> basis[4 * N];
    vector<int> merge_tree(vector<int> le, vector<int> ri) {
        vector<int> gauss;
        for(int i = 0; i < le.size(); i++)
            gauss.pb(le[i]);
        for(int i = 0; i < ri.size(); i++)
            gauss.pb(ri[i]);
        int cur = 0;
        for(int bit = 30; bit >= 0; bit--) {
            for(int i = cur; i < gauss.size(); i++) {
                if((gauss[i] & (1 << bit))) {
                    swap(gauss[i], gauss[cur]);
                    for(int j = 0; j < gauss.size(); j++) {
                        if(j != cur && (gauss[j] & (1 << bit)))
                            gauss[j] ^= gauss[cur];
                    }
                    cur++;
                    break;
                }
            }
        }
        bool ok = 0; vector<int> res;
        for(int i = 0; i < gauss.size(); i++) {
            if(gauss[i] > 1)
                res.pb(gauss[i]);
            else {
                if(gauss[i] == 1) {
                    res.pb(gauss[i]);
                    ok = 1;
                }
            }
        }
        return res;
    }
    void lzupdate(int k, int l, int r) {
        if(!lz[k]) return ;
        for(int i = 0; i < basis[k].size(); i++) {
            if(basis[k][i] & 1)
                basis[k][i] ^= lz[k];
        }
        if(l != r) {
            lz[k << 1] ^= lz[k];
            lz[k << 1 | 1] ^= lz[k];
        }
        lz[k] = 0;
    }
    void build_tree(int k, int l, int r) {
        if(l == r) {
            basis[k].pb(a[l]);
            return ;
        }
        int md = (l + r) >> 1;
        build_tree(k << 1, l, md);
        build_tree(k << 1 | 1, md + 1, r);
        basis[k] = merge_tree(basis[k << 1], basis[k << 1 | 1]);
    }
    void update(int k, int l, int r, int L, int R, int val) {
        lzupdate(k, l, r);
        if(r < L || R < l || L > R) return ;
        if(L <= l && r <= R) {
            lz[k] ^= val;
            lzupdate(k, l, r);
            return ;
        }
        int md = (l + r) >> 1;
        update(k << 1, l, md, L, R, val);
        update(k << 1 | 1, md + 1, r, L, R, val);
        basis[k] = merge_tree(basis[k << 1], basis[k << 1 | 1]);
    }
    vector<int> get(int k, int l, int r, int L, int R) {
        lzupdate(k, l, r);
        if(r < L || R < l || L > R) {
            vector<int> temp; temp.pb(0);
            return temp;
        }
        if(L <= l && r <= R)
            return basis[k];
        int md = (l + r) >> 1;
        vector<int> le = get(k << 1, l, md, L, R);
        vector<int> ri = get(k << 1 | 1, md + 1, r, L, R);
        return merge_tree(le, ri);
    }
}it;

int main() {
    cin.tie(0), ios_base::sync_with_stdio(0);
    cin >> n >> q;
    for(int i = 1; i <= n; i++) {
        cin >> a[i];
        a[i] = ((a[i] << 1) | 1);
    }
    it.build_tree(1, 1, n);
    while(q--) {
        int type, l, r;
        cin >> type;
        cin >> l >> r;
        if(type == 1) {
            int x;
            cin >> x;
            x = (x << 1);
            it.update(1, 1, n, l, r, x);
        }
        else {
            vector<int> tmp = it.get(1, 1, n, l, r);
            long long sum = 1;
            for(int i = 0; i < tmp.size(); i++) {
                if(tmp[i] > 1)
                    sum *= 2ll;
            }
            cout << sum << "\n";
        }
    }
}


#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <limits>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;

// {{{
// clang-format off
#define all(a) (a).begin(), (a).end()
#define sz(a) static_cast<int>((a).size())
#define fillchar(a, x) memset(a, x, sizeof(a))
#define rep(i, a, b) for (int i = int(a); i <= int(b); ++i)
#define irep(i, a, b) for (int i = int(a); i >= int(b); --i)
#define replr(i, a, b) rep(i, a, (b)-1)
#define reprl(i, a, b) irep(i, (b)-1, a)
#define repn(i, n) rep(i, 0, (n)-1)
#define irepn(i, n) irep(i, (n)-1, 0)
#define fi first
#define se second
#define pb push_back
#define mp make_pair
typedef long long LL;
typedef long double LD;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
typedef pair<double, double> PDD;
typedef vector<int> VI;
typedef vector<LL> VL;
typedef vector<double> VD;
typedef vector<string> VS;
typedef vector<PII> VPI;
typedef vector<PLL> VPL;
template <class T, class S> ostream& operator<<(ostream& os, const pair<T, S>& v) { return os << "(" << v.first << ", " << v.second << ")"; }
template <class T> ostream& operator<<(ostream& os, const vector<T>& v) { os << "["; repn(i, sz(v)) { if(i) os << ", "; os << v[i]; } return os << "]"; }
template <class T> bool setmax(T& _a, T _b) { if(_a < _b) { _a = _b; return true; } return false; }
template <class T> bool setmin(T& _a, T _b) { if(_b < _a) { _a = _b; return true; } return false; }
template <class T> T gcd(T _a, T _b) { return _b == 0 ? _a : gcd(_b, _a % _b); }
// clang-format on
// }}}

const int N = 200000;

struct BaseBuilder {
    int head[31];
    BaseBuilder() { fillchar(head, 0); }
    void add(int x) {
        irep(i, 30, 0) if(x & (1 << i)) {
            if(head[i] == 0) {
                head[i] = x;
                break;
            } else {
                x ^= head[i];
            }
        }
    }
    VI build() const {
        VI r;
        irep(i, 30, 0) if(head[i]) r.pb(head[i]);
        return r;
    }
};

struct Value {
    int le;
    VI bases;

    void operator^=(int x) { le ^= x; }
    Value operator+(const Value& v) const {
        BaseBuilder builder;
        for(int x : bases) builder.add(x);
        for(int x : v.bases) builder.add(x);
        builder.add(le ^ v.le);
        Value r;
        r.le = le;
        r.bases = builder.build();
        return r;
    }
};

Value tr[N * 4];
int buf[N * 4];

void release(int x) {
    if(buf[x] != 0) {
        tr[x * 2 + 1] ^= buf[x];
        buf[x * 2 + 1] ^= buf[x];
        tr[x * 2 + 2] ^= buf[x];
        buf[x * 2 + 2] ^= buf[x];
        buf[x] = 0;
    }
}

void modify(int x, int l, int r, int st, int en, int val) {
    if(st <= l && r <= en) {
        tr[x] ^= val;
        buf[x] ^= val;
        return;
    }
    release(x);
    const int m = (l + r) / 2;
    if(st < m) modify(x * 2 + 1, l, m, st, en, val);
    if(m < en) modify(x * 2 + 2, m, r, st, en, val);
    tr[x] = tr[x * 2 + 1] + tr[x * 2 + 2];
}

Value get(int x, int l, int r, int st, int en) {
    if(st <= l && r <= en) {
        return tr[x];
    }
    release(x);
    const int m = (l + r) / 2;
#define L get(x * 2 + 1, l, m, st, en)
#define R get(x * 2 + 2, m, r, st, en)
    if(st < m && m < en) {
        return L + R;
    } else if(st < m) {
        return L;
    } else {
        return R;
    }
}

int main() {
    int n, q;
    scanf("%d%d", &n, &q);
    repn(i, n) {
        int x;
        scanf("%d", &x);
        modify(0, 0, n, i, i + 1, x);
    }
    while(q--) {
        int type, l, r;
        scanf("%d%d%d", &type, &l, &r);
        --l;
        if(type == 1) {
            int x;
            scanf("%d", &x);
            modify(0, 0, n, l, r, x);
        } else {
            Value ret = get(0, 0, n, l, r);
            // cout << ret.le << " " << ret.bases << endl;
            BaseBuilder builder;
            for(int x : ret.bases) builder.add(x);
            builder.add(ret.le);
            int ans = 1 << sz(builder.build());
            printf("%d\n", ans);
        }
    }
    return 0;
}


#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <limits>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;

// {{{
// clang-format off
#define all(a) (a).begin(), (a).end()
#define sz(a) static_cast<int>((a).size())
#define fillchar(a, x) memset(a, x, sizeof(a))
#define rep(i, a, b) for (int i = int(a); i <= int(b); ++i)
#define irep(i, a, b) for (int i = int(a); i >= int(b); --i)
#define replr(i, a, b) rep(i, a, (b)-1)
#define reprl(i, a, b) irep(i, (b)-1, a)
#define repn(i, n) rep(i, 0, (n)-1)
#define irepn(i, n) irep(i, (n)-1, 0)
#define fi first
#define se second
#define pb push_back
#define mp make_pair
typedef long long LL;
typedef long double LD;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
typedef pair<double, double> PDD;
typedef vector<int> VI;
typedef vector<LL> VL;
typedef vector<double> VD;
typedef vector<string> VS;
typedef vector<PII> VPI;
typedef vector<PLL> VPL;
template <class T, class S> ostream& operator<<(ostream& os, const pair<T, S>& v) { return os << "(" << v.first << ", " << v.second << ")"; }
template <class T> ostream& operator<<(ostream& os, const vector<T>& v) { os << "["; repn(i, sz(v)) { if(i) os << ", "; os << v[i]; } return os << "]"; }
template <class T> bool setmax(T& _a, T _b) { if(_a < _b) { _a = _b; return true; } return false; }
template <class T> bool setmin(T& _a, T _b) { if(_b < _a) { _a = _b; return true; } return false; }
template <class T> T gcd(T _a, T _b) { return _b == 0 ? _a : gcd(_b, _a % _b); }
// clang-format on
// }}}

const int N = 200000;

struct BaseBuilder {
    int head[31];
    BaseBuilder() { fillchar(head, 0); }
    void add(int x) {
        irep(i, 30, 0) if(x & (1 << i)) {
            if(head[i] == 0) {
                head[i] = x;
                break;
            } else {
                x ^= head[i];
            }
        }
    }
    VI build() const {
        VI r;
        irep(i, 30, 0) if(head[i]) r.pb(head[i]);
        return r;
    }
};

struct Value {
    int le;
    VI bases;

    void operator^=(int x) { le ^= x; }
    Value operator+(const Value& v) const {
        BaseBuilder builder;
        for(int x : bases) builder.add(x);
        for(int x : v.bases) builder.add(x);
        builder.add(le ^ v.le);
        Value r;
        r.le = le;
        r.bases = builder.build();
        return r;
    }
};

Value tr[N];
int buf[N];

void release(int x) {
    if(buf[x] != 0) {
        tr[x * 2 + 1] ^= buf[x];
        buf[x * 2 + 1] ^= buf[x];
        tr[x * 2 + 2] ^= buf[x];
        buf[x * 2 + 2] ^= buf[x];
        buf[x] = 0;
    }
}

void modify(int x, int l, int r, int st, int en, int val) {
    if(st <= l && r <= en) {
        tr[x] ^= val;
        buf[x] ^= val;
        return;
    }
    release(x);
    const int m = (l + r) / 2;
    if(st < m) modify(x * 2 + 1, l, m, st, en, val);
    if(m < en) modify(x * 2 + 2, m, r, st, en, val);
    tr[x] = tr[x * 2 + 1] + tr[x * 2 + 2];
}

Value get(int x, int l, int r, int st, int en) {
    if(st <= l && r <= en) {
        return tr[x];
    }
    release(x);
    const int m = (l + r) / 2;
#define L get(x * 2 + 1, l, m, st, en)
#define R get(x * 2 + 2, m, r, st, en)
    if(st < m && m < en) {
        return L + R;
    } else if(st < m) {
        return L;
    } else {
        return R;
    }
}

int main() {
    int n, q;
    scanf("%d%d", &n, &q);
    repn(i, n) {
        int x;
        scanf("%d", &x);
        modify(0, 0, n, i, i + 1, x);
    }
    while(q--) {
        int type, l, r;
        scanf("%d%d%d", &type, &l, &r);
        --l;
        if(type == 1) {
            int x;
            scanf("%d", &x);
            modify(0, 0, n, l, r, x);
        } else {
            Value ret = get(0, 0, n, l, r);
            //cout << ret.le << " " << ret.bases << endl;
            BaseBuilder builder;
            for(int x : ret.bases) builder.add(x);
            builder.add(ret.le);
            int ans = 1 << sz(builder.build());
            printf("%d\n", ans);
        }
    }
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define endl '\n'
#define fi first
#define se second
#define MOD(n,k) ( ( ((n) % (k)) + (k) ) % (k))
#define forn(i,n) for (int i = 0; i < n; i++)
#define forr(i,a,b) for (int i = a; i <= b; i++)
#define all(v) v.begin(), v.end()
#define pb(x) push_back(x)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> ii;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ii> vii;

const int MX = 200005;

int n, q, a[MX], t, l, r, k, lz[4*MX];
vi st[4*MX], res;

void merge (vi &a, vi &b, vi &c) {
	c.clear();

	for (int y : a) {
		for (int x : c)
			if (x & -x & y)
				y ^= x;
		if (y) c.pb(y);
	}

	for (int y : b) {
		for (int x : c)
			if (x & -x & y)
				y ^= x;
		if (y) c.pb(y);
	}

	sort(all(c));
}

void push (int i, int j, int pos) {
	for (int &x : st[pos])
		if (x & 1)
			x ^= lz[pos];
	vi aux = st[pos];
	merge(aux, aux, st[pos]);

	if (i < j) {
		lz[pos*2] ^= lz[pos];
		lz[pos*2+1] ^= lz[pos];
	}

	lz[pos] = 0;
}

void build (int i, int j, int pos) {
	if (i == j) {
		st[pos].pb(1);
		return;
	}

	int m = (i+j)/2;
	build(i, m, pos*2);
	build(m+1, j, pos*2+1);
	merge(st[pos*2], st[pos*2+1], st[pos]);
}

void update (int i, int j, int pos, int a, int b, int k) {
	if (lz[pos]) push(i, j, pos);

	if (b < i || j < a) return;
	if (a <= i && j <= b) {
		lz[pos] ^= k;
		push(i, j, pos);
		return;
	}

	int m = (i+j)/2;
	update(i, m, pos*2, a, b, k);
	update(m+1, j, pos*2+1, a, b, k);
	merge(st[pos*2], st[pos*2+1], st[pos]);
}

void query (int i, int j, int pos, int a, int b) {
	if (lz[pos]) push(i, j, pos);

	if (b < i || j < a) return;
	if (a <= i && j <= b) {
		vi aux = res;
		merge(aux, st[pos], res);
		return;
	}

	int m = (i+j)/2;
	query(i, m, pos*2, a, b);
	query(m+1, j, pos*2+1, a, b);
}

int main () {
	ios_base::sync_with_stdio(0); cin.tie(0);

	cin >> n >> q;

	build(1, n, 1);

	for (int i = 1; i <= n; i++) {
		cin >> a[i];
		update(1, n, 1, i, i, 2 * a[i]);
	}

	while (q--) {
		cin >> t;

		if (t == 1) {
			cin >> l >> r >> k;
			update(1, n, 1, l, r, 2 * k);
		} else {
			cin >> l >> r;

			res.clear();
			query(1, n, 1, l, r);

			vi aux = res;
			for (int &x : aux)
				x /= 2;
			merge(aux, aux, res);

			cout << (1ll << res.size()) << endl;
		}
	}

	return 0;
}


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

const int MN = 200010;

int N, Q;
int A[MN];

vector<int> gauss(vector<int> &a) {
    vector<int> ret, chk(a.size(), 0);

    while(1) {
        int mx = -1, p = -1;
        for(int i = 0; i < a.size(); i++) if(!chk[i] && mx < a[i]) mx = a[i], p = i;
        if(mx <= 0) {
            if(mx == 0) ret.push_back(0);
            break;
        }

        chk[p] = 1;
        ret.push_back(mx);
        for(int i = 0; i < a.size(); i++) if(!chk[i] && a[i] > (mx ^ a[i])) a[i] ^= mx;
    }
    return ret;
}

vector<int> mrg(vector<int> &a, vector<int> &b) {
    vector<int> tmp;
    for(int i = 0; i < a.size(); i++) tmp.push_back(a[i]);
    for(int i = 0; i < b.size(); i++) tmp.push_back(b[i]);
    return gauss(tmp);
}

struct BIT {
    vector<vector<int> > tree;
    vector<int> lazy;
    void init() {
        tree = vector<vector<int> >(4 * N);
        lazy = vector<int>(4 * N, 0);
        build(0, N - 1, 1);
    }
    void build(int l, int r, int n) {
        if(l == r) {
            tree[n].push_back(A[l]);
            return;
        }
        int m = (l + r)>>1;
        build(l, m, 2*n);
        build(m + 1, r, 2*n + 1);
        tree[n] = mrg(tree[2*n], tree[2*n + 1]);
    }
    void prop(int l, int r, int n) {
        if(l != r) {
            for(int i = 0; i < tree[2*n].size(); i++) tree[2*n][i] ^= lazy[n];
            tree[2*n] = gauss(tree[2*n]);
            lazy[2*n] ^= lazy[n];
            for(int i = 0; i < tree[2*n + 1].size(); i++) tree[2*n + 1][i] ^= lazy[n];
            tree[2*n + 1] = gauss(tree[2*n + 1]);
            lazy[2*n + 1] ^= lazy[n];
            lazy[n] = 0;
        }
    }
    void upd(int a, int b, int d, int l, int r, int n) {
        if(b < l || r < a) return;
        if(a <= l && r <= b) {
            for(int i = 0; i < tree[n].size(); i++) tree[n][i] ^= d;
            tree[n] = gauss(tree[n]);
            lazy[n] ^= d;
            return;
        }
        prop(l, r, n);
        int m = (l + r)>>1;
        upd(a, b, d, l, m, 2*n);
        upd(a, b, d, m + 1, r, 2*n + 1);
        tree[n] = mrg(tree[2*n], tree[2*n + 1]);
    }
    vector<int> quer(int a, int b, int l, int r, int n) {
        if(b < l || r < a) return vector<int>();
        if(a <= l && r <= b) return tree[n];
        prop(l, r, n);
        int m = (l + r)>>1;
        vector<int> L = quer(a, b, l, m, 2*n);
        vector<int> R = quer(a, b, m + 1, r, 2*n + 1);
        return mrg(L, R);
    }
} bit;

int main() {
    scanf("%d %d", &N, &Q);

    for(int i = 0; i < N; i++) {
        scanf("%d", &A[i]);
    }

    bit.init();
    for(int i = 0; i < Q; i++) {
        int t; scanf("%d", &t);

        /*
        for(int j = 0; j < N; j++) {
            vector<int> tmp = bit.quer(j, j, 0, N - 1, 1);
            if(tmp.size()) cout << tmp[0] << ' ';
            else cout << -1 << ' ';
        }
        cout << endl;
        //*/

        if(t == 1) {
            int l, r, k; scanf("%d %d %d", &l, &r, &k);
            l--; r--;

            bit.upd(l, r, k, 0, N - 1, 1);
        }
        if(t == 2) {
            int l, r; scanf("%d %d", &l, &r);
            l--; r--;

            vector<int> t = bit.quer(l, r, 0, N - 1, 1);
            int n = t.size();
            if(t.back() == 0) n--;
            printf("%d\n", (1 << n));
        }
    }
}


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

const int MN = 200010;

int N, Q;
int A[MN], B[MN];

struct BIT1 {
    vector<int> tree;
    void init() {
        tree = vector<int>(4 * N, 0);
    }
    void upd(int a, int b, int d, int l, int r, int n) {
        if(b < l || r < a) return;
        if(a <= l && r <= b) {
            tree[n] ^= d;
            return;
        }
        int m = (l + r)>>1;
        upd(a, b, d, l, m, 2*n);
        upd(a, b, d, m + 1, r, 2*n + 1);
    }
    int quer(int idx, int l, int r, int n) {
        if(idx < l || r < idx) return 0;
        int ret = tree[n];
        if(l == r) return ret;
        int m = (l + r)>>1;
        ret ^= quer(idx, l, m, 2*n);
        ret ^= quer(idx, m + 1, r, 2*n + 1);
        return ret;
    }
} bit1;

vector<int> gauss(vector<int> &a) {
    vector<int> ret;

    while(1) {
        int mx = 0;
        for(int i = 0; i < a.size(); i++) mx = max(mx, a[i]);
        if(mx <= 0) break;

        ret.push_back(mx);
        for(int i = 0; i < a.size(); i++) if(a[i] > (mx ^ a[i])) a[i] ^= mx;
    }
    return ret;
}

vector<int> mrg(vector<int> &a, vector<int> &b) {
    vector<int> tmp;
    for(int i = 0; i < a.size(); i++) tmp.push_back(a[i]);
    for(int i = 0; i < b.size(); i++) tmp.push_back(b[i]);
    return gauss(tmp);
}

struct BIT2 {
    vector<vector<int> > tree;
    void init() {
        tree = vector<vector<int> >(4 * N);
        build(0, N - 1, 1);
    }
    void build(int l, int r, int n) {
        if(l == r) {
            if(B[l]) tree[n].push_back(B[l]);
            return;
        }
        int m = (l + r)>>1;
        build(l, m, 2*n);
        build(m + 1, r, 2*n + 1);
        tree[n] = mrg(tree[2*n], tree[2*n + 1]);
    }
    void upd(int idx, int val, int l, int r, int n) {
        if(idx < l || r < idx) return;
        if(l == r) {
            if(tree[n].size()) tree[n][0] ^= val;
            else tree[n].push_back(val);
            while(tree[n].size() && !tree[n].back()) tree[n].pop_back();
            return;
        }
        int m = (l + r)>>1;
        upd(idx, val, l, m, 2*n);
        upd(idx, val, m + 1, r, 2*n + 1);
        tree[n] = mrg(tree[2*n], tree[2*n + 1]);
    }
    vector<int> quer(int a, int b, int l, int r, int n) {
        if(b < l || r < a) return vector<int>();
        if(a <= l && r <= b) return tree[n];
        int m = (l + r)>>1;
        vector<int> L = quer(a, b, l, m, 2*n);
        vector<int> R = quer(a, b, m + 1, r, 2*n + 1);
        return mrg(L, R);
    }
} bit2;

int main() {
    scanf("%d %d", &N, &Q);

    for(int i = 0; i < N; i++) {
        scanf("%d", &A[i]);
    }
    for(int i = 1; i < N; i++) {
        B[i] = A[i - 1] ^ A[i];
    }

    bit1.init();
    bit2.init();
    for(int i = 0; i < Q; i++) {
        int t; scanf("%d", &t);

        if(t == 1) {
            int l, r, k; scanf("%d %d %d", &l, &r, &k);
            l--; r--;

            bit1.upd(l, r, k, 0, N - 1, 1);
            bit2.upd(l, k, 0, N - 1, 1);
            bit2.upd(r + 1, k, 0, N - 1, 1);
        }
        if(t == 2) {
            int l, r; scanf("%d %d", &l, &r);
            l--; r--;

            vector<int> t = bit2.quer(l + 1, r, 0, N - 1, 1);
            int d = bit1.quer(l, 0, N - 1, 1);
            d ^= A[l];
            if(d) {
                t.push_back(d);
                t = gauss(t);
            }

            printf("%d\n", (1 << t.size()));
        }
    }
}


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

const int MN = 200010;

int N, Q;
int A[MN];

vector<int> gauss(vector<int> &a) {
    vector<int> ret;

    while(1) {
        int mx = 0;
        for(int i = 0; i < a.size(); i++) mx = max(mx, a[i]);
        if(mx == 0) break;

        ret.push_back(mx);
        for(int i = 0; i < a.size(); i++) if(a[i] > (mx ^ a[i])) a[i] ^= mx;
    }
    return ret;
}

vector<int> mrg(vector<int> &a, vector<int> &b) {
    vector<int> tmp;
    for(int i = 0; i < a.size(); i++) tmp.push_back(a[i]);
    for(int i = 0; i < b.size(); i++) tmp.push_back(b[i]);
    return gauss(tmp);
}

struct BIT {
    vector<vector<int> > tree;
    vector<int> lazy;
    void init() {
        tree = vector<vector<int> >(4 * N);
        lazy = vector<int>(4 * N, 0);
        build(0, N - 1, 1);
    }
    void build(int l, int r, int n) {
        if(l == r) {
            if(A[l]) tree[n].push_back(A[l]);
            return;
        }
        int m = (l + r)>>1;
        build(l, m, 2*n);
        build(m + 1, r, 2*n + 1);
        tree[n] = mrg(tree[2*n], tree[2*n + 1]);
    }
    void prop(int l, int r, int n) {
        if(l != r) {
            for(int i = 0; i < tree[2*n].size(); i++) tree[2*n][i] ^= lazy[n];
            tree[2*n] = gauss(tree[2*n]);
            lazy[2*n] ^= lazy[n];
            for(int i = 0; i < tree[2*n + 1].size(); i++) tree[2*n + 1][i] ^= lazy[n];
            tree[2*n + 1] = gauss(tree[2*n + 1]);
            lazy[2*n + 1] ^= lazy[n];
            lazy[n] = 0;
        }
    }
    void upd(int a, int b, int d, int l, int r, int n) {
        if(b < l || r < a) return;
        if(a <= l && r <= b) {
            for(int i = 0; i < tree[n].size(); i++) tree[n][i] ^= d;
            tree[n] = gauss(tree[n]);
            lazy[n] ^= d;
            return;
        }
        prop(l, r, n);
        int m = (l + r)>>1;
        upd(a, b, d, l, m, 2*n);
        upd(a, b, d, m + 1, r, 2*n + 1);
        tree[n] = mrg(tree[2*n], tree[2*n + 1]);
    }
    vector<int> quer(int a, int b, int l, int r, int n) {
        if(b < l || r < a) return vector<int>();
        if(a <= l && r <= b) return tree[n];
        prop(l, r, n);
        int m = (l + r)>>1;
        vector<int> L = quer(a, b, l, m, 2*n);
        vector<int> R = quer(a, b, m + 1, r, 2*n + 1);
        return mrg(L, R);
    }
} bit;

int main() {
    scanf("%d %d", &N, &Q);

    for(int i = 0; i < N; i++) {
        scanf("%d", &A[i]);
    }

    bit.init();
    for(int i = 0; i < Q; i++) {
        int t; scanf("%d", &t);

        if(t == 1) {
            int l, r, k; scanf("%d %d %d", &l, &r, &k);
            l--; r--;

            bit.upd(l, r, k, 0, N - 1, 1);
        }
        if(t == 2) {
            int l, r; scanf("%d %d", &l, &r);
            l--; r--;

            int n = bit.quer(l, r, 0, N - 1, 1).size();
            printf("%d\n", (1 << n));
        }
    }
}


#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int n, q, flag[N << 3], w[N];
struct LinearBasis{
	int base[32], num;
	void init(){ memset( base, 0, sizeof(base) ); num = 0; }
	int count(){
		int res = 0;
		for( int i = 0; i <= 29; i ++ ){ if( base[i] ) res++; }
		return res;
	}
	void insert( int x ){
		for( int i = 29; i >= 0; i -- ){
			if( (x >> i) & 1 ){
				if( base[i] ) x ^= base[i];
				else {
					base[i] = x; break;
				}
			}
		}
	}
	LinearBasis operator + ( const LinearBasis & a ) const{
		LinearBasis res; res.init();
		for( int i = 0; i <= 29; i ++ ){
			res.insert(base[i]);
			res.insert(a.base[i]);
		}
		res.insert(num^a.num);
		res.num = a.num;
		return res;
	}
}t[N << 3], res;
void pushdown( int k ){
	if( flag[k] ){
		flag[k << 1] ^= flag[k];
		flag[k << 1 | 1] ^= flag[k];
		t[k << 1].num ^= flag[k]; t[k << 1 | 1].num ^= flag[k];
		flag[k] = 0;
	}
}
void update( int k ){ t[k] = t[k << 1] + t[k << 1 | 1]; }
void build( int k, int l, int r ){
	t[k].init();
	if( l == r ){
		t[k].num = w[l];
		return ;
	}
	int mid = l + r >> 1;
	build( k << 1, l, mid );
	build( k << 1 | 1, mid + 1, r );
	update( k );
}
void modify( int k, int l, int r, int L, int R, int v ){
	if( l >= L && r <= R ){ flag[k] ^= v; t[k].num ^= v; return ; }
	pushdown( k );
	int mid = l + r >> 1;
	if( L <= mid ) modify( k << 1, l, mid, L, R, v );
	if( R >  mid ) modify( k << 1 | 1, mid + 1, r, L, R, v );
	update( k );
}/*sis query( int k, int l, int r, int L, int R ){
	if( l >= L && r <= R ){ return t[k]; }
	pushdown( k ); LinearBasis as; as.init();
	int mid = l + r >> 1;
	if( L <= mid ) as = as + query( k << 1, l, mid, L, R );
	if( R >  mid ) as = as + query( k << 1 | 1, mid + 1, r, L, R );
	update( k );
	return as;
}*/
void query(int l,int r,int st,int L,int R) {
    if(l >= L && r <= R) {
        res = res + t[st];
        return ;
    }
    pushdown(st);
    int mid = (l+r) >>1;
    if(L<=mid) query(l,mid,st<<1,L,R);
    if(R>mid)  query(mid+1,r,st<<1|1,L,R);
    t[st] = t[st<<1] + t[st<<1|1];
}

int main() {
	int opt, a, b, v;
	memset( flag, 0, sizeof(flag) );
	scanf( "%d%d", &n, &q );
	for( int i = 1; i <= n; i ++ ) scanf( "%d", &w[i] );
	build( 1, 1, n );
	while( q -- ){
		scanf( "%d%d%d", &opt, &a, &b );
		if( opt == 1 ){ scanf( "%d", &v ); modify( 1, 1, n, a, b, v ); }
		else{ res.init(); query( 1, n, 1,  a, b ), printf( "%d\n", 1 << res.count() ); }
	}
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
struct LinearBasis{
	int base[32], num;
	void init(){ memset( base, 0, sizeof(base) ); num = 0; }
	int count(){
		int res = 0;
		for( int i = 0; i <= 29; i ++ ){ if( base[i] ) res++; }
		return res;
	}
	void insert( int x ){
		for( int i = 29; i >= 0; i -- ){
			if( (x >> i) & 1 ){
				if( base[i] ) x ^= base[i];
				else {
					base[i] = x; break;
				}
			}
		}
	}
	LinearBasis operator + ( const LinearBasis & a ) const{
		LinearBasis res; res.init();
		for( int i = 0; i <= 29; i ++ ){
			res.insert(base[i]);
			res.insert(a.base[i]);
		}
		res.insert(num^a.num);
		res.num = a.num;
		return res;
	}
}t[N << 3], res;
int n, q, flag[N << 2], w[N];
void pushdown( int k ){
	if( flag[k] ){
		flag[k << 1] ^= flag[k];
		flag[k << 1 | 1] ^= flag[k];
		t[k << 1].num ^= flag[k]; t[k << 1 | 1].num ^= flag[k];
		flag[k] = 0;
	}
}
void update( int k ){ t[k] = t[k << 1] + t[k << 1 | 1]; }
void build( int k, int l, int r ){
	t[k].init();
	if( l == r ){
		t[k].num = w[l];
		return ;
	}
	int mid = l + r >> 1;
	build( k << 1, l, mid );
	build( k << 1 | 1, mid + 1, r );
	update( k );
}
void modify( int k, int l, int r, int L, int R, int v ){
	if( l >= L && r <= R ){ flag[k] ^= v; t[k].num ^= v; return ; }
	pushdown( k );
	int mid = l + r >> 1;
	if( L <= mid ) modify( k << 1, l, mid, L, R, v );
	if( R >  mid ) modify( k << 1 | 1, mid + 1, r, L, R, v );
	update( k );
}
LinearBasis query( int k, int l, int r, int L, int R ){
	if( l >= L && r <= R ){ return t[k]; }
	pushdown( k ); LinearBasis as; as.init();
	int mid = l + r >> 1;
	if( L <= mid ) as = as + query( k << 1, l, mid, L, R );
	if( R >  mid ) as = as + query( k << 1 | 1, mid + 1, r, L, R );
	update( k );
	return as;
}

int main() {
	int opt,a,b,v;
	memset( flag, 0, sizeof(flag) );
	scanf( "%d%d", &n, &q );
	for( int i = 1; i <= n; i ++ ) scanf( "%d", &w[i] );
	build( 1, 1, n );
	while( q -- ){
		scanf( "%d%d%d", &opt, &a, &b );
		if( opt == 1 ){ scanf( "%d", &v ); modify( 1, 1, n, a, b, v ); }
		else{ printf( "%d\n", 1 << query( 1, 1, n, a, b ).count() ); }
	}
	return 0;
}


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

void binary_basis_insert(vector<int>& w, int a) {
    for(auto v : w) {
        if(v & (-v) & a) {
            a ^= v;
        }
    }
    if(a == 0) {
        return;
    }
    for(auto& v : w) {
        if(a & (-a) & v) {
            v ^= a;
        }
    }
    w.push_back(a);
}

vector<int> binary_basis(vector<int> const& w) {
    vector<int> res;
    for(auto v : w) {
        binary_basis_insert(res, v);
    }
    return res;
}

struct binary {
    using type = vector<int>;
    static type id() {
        return type();
    }
    static type op(type l, type r) {
        if(l.size() < r.size()) {
            swap(l, r);
        }
        for(auto v : r) {
            binary_basis_insert(l, v);
        }
        return binary_basis(l);
    }
};

template<typename Monoid>
class segment_tree {
    using T = typename Monoid::type;

public:
    segment_tree(std::vector<T> const& init)
        : sz(init.size()),
          n(expand(init.size()))
    {
        dat.assign(n*2, Monoid::id());
        std::copy(begin(init), end(init), begin(dat) + n);
        for(int i = n - 1; i >= 0; --i) {
            dat[i] = Monoid::op(dat[i * 2], dat[i * 2 + 1]);
        }
    }

    segment_tree(int const n, T const& init = Monoid::id())
        : segment_tree(std::vector<T>(n, init))
    {}

    void update(int p, T val) {
        assert(0 <= p && p < sz);
        dat[p += n] = val;
        while(p /= 2) {
            dat[p] = Monoid::op(dat[p * 2], dat[p * 2 + 1]);
        }
    }

    // [l, r)
    T query(int l, int r) const {
        assert(0 <= l && l <= r && r <= sz);
        l += n;
        r += n;
        T res1 = Monoid::id(),
          res2 = Monoid::id();
        while(l != r) {
            if(l & 1) {
                res1 = Monoid::op(res1, dat[l++]);
            }
            if(r & 1) {
                res2 = Monoid::op(dat[--r], res2);
            }
            l /= 2;
            r /= 2;
        }
        return Monoid::op(res1, res2);
    }

    int size() const {
        return sz;
    }

    void print() {
        for(int i = n; i < 2 * n; ++i) {
            if(dat[i].size() == 0) {
                continue;
            }
            cout << dat[i][0] << endl;
        }
    }

private:
    int expand(int n) const {
        return n == 1 ? n : expand((n + 1) / 2) * 2;
    }

private:
    const int sz;
    const int n;
    std::vector<T> dat;
};

// 0-indexed
template <typename T>
class fenwick_tree {
public:
    fenwick_tree(int n) : n(n), dat(n, 0) {}

    void add(int i, T value) {
        for(; i<n; i |= i + 1) {
            dat[i] ^= value;
        }
    }

    T sum(int i) const {
        T res = 0;
        for(; i>=0; i = (i & (i+1)) - 1) {
            res ^= dat[i];
        }
        return res;
    }
    // [l, r)
    T sum(int l, int r) const {
        return sum(r-1) ^ sum(l-1);
    }

private:
    const int n;
    std::vector<T> dat;
};

int main() {
    int n, q;
    cin >> n >> q;
    vector<int> a(n);
    fenwick_tree<int> bit(n + 1);
    for(int i = 0; i < n; ++i) {
        cin >> a[i];
        bit.add(i, a[i]);
        bit.add(i + 1, a[i]);
    }

    vector<int> b(n);
    for(int i = 1; i < n; ++i) {
        b[i] = a[i - 1] ^ a[i];
    }

    vector<vector<int>> init(n);
    for(int i = 0; i < n; ++i) {
        init[i].push_back(b[i]);
    }
    segment_tree<binary> seg(init);

    for(int i = 0; i < q; ++i) {
        int t;
        cin >> t;
        if(t == 1) {
            int l, r, k;
            cin >> l >> r >> k;
            l--;
            bit.add(l, k);
            bit.add(r, k);
            seg.update(l, {bit.sum(l) ^ bit.sum(l - 1)});
            if(r < n) {
                seg.update(r, {bit.sum(r) ^ bit.sum(r - 1)});
            }
        } else {
            int l, r;
            cin >> l >> r;
            l--;
            auto res = seg.query(l + 1, r);
            binary_basis_insert(res, bit.sum(l));
            cout << (1LL << res.size()) << endl;
        }
    }
}


#include<bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#define mms(a,n) memset(a,0,sizeof((a)[0])*(n))
#define mmp(a,b,n) memcpy(a,b,sizeof((b)[0])*(n))
#define lowbit(x) ((x)&-(x))
#define pb push_back
#define fi first
#define se second
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define lowbit(x) ((x)&-(x))
#define fo(i,l,r) for(register int i=l,_lim_=r;i<=_lim_;i++)
#define fd(i,r,l) for(register int i=r,_lim_=l;i>=_lim_;i--)

using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pi;
typedef double db;
typedef long double ldb;

namespace io{
	const int L=(1<<21)+1;
	char ibuf[L],*iS,*iT,obuf[L],*oS=obuf,*oT=obuf+L-1,c,st[55];int f,tp;
	#ifdef whzzt
		#define gc() getchar()
	#else
		#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,L,stdin),(iS==iT?EOF:*iS++)):*iS++)
	#endif
	inline void flush(){fwrite(obuf,1,oS-obuf,stdout);oS=obuf;}
	inline void putc(char x){*oS++=x;if(oS==oT)flush();}
	template<class I>
	inline void gi(I&x){
		for(f=1,c=gc();c<'0'||c>'9';c=gc())if(c=='-')f=-1;
		for(x=0;c<='9'&&c>='0';c=gc())x=x*10+(c&15);x*=f;
	}
	template<class I>
	inline void print(I x){
		if(!x)putc('0');if(x<0)putc('-'),x=-x;
		while(x)st[++tp]=x%10+'0',x/=10;
		while(tp)putc(st[tp--]);
	}
	inline void gs(char*s,int&l){
		for(c=gc();c!='_'&&(c<'a'||c>'z');c=gc());
		for(l=0;c=='_'||c<='z'&&c>='a';c=gc())s[l++]=c;
	}
};
using io::putc;
using io::gi;
using io::gs;
using io::print;

const int N=200005,M=32,L=525005;

int n,q,a[N],mx;
struct LinearBase{
	int a[M],m;
	int find(int k){
		for(int i=1;i<=m;i++)if((k^a[i])<k)k^=a[i];
		return k;
	}
	void ext(int k){
		if(k=find(k)){
			int j=1;
			while(k<=a[j])j++;
			++m;for(int i=m;i>j;i--)a[i]=a[i-1];
			a[j]=k;
			for(int i=1;i<j;i++)if((k^a[i])<a[i])a[i]^=k;
		}
	}
	friend LinearBase operator+(const LinearBase&a,const LinearBase&b){
		if((1ll<<a.m)>mx)return a;if((1ll<<b.m)>mx)return b;
		LinearBase ret=a;
		for(int i=1;i<=b.m;i++)ret.ext(b.a[i]);
		return ret;
	}
	void clear(){while(m)a[m--]=0;}
}seg[L],ans;

void build(int x,int l,int r){
	if(l==r){
		seg[x].ext(a[l]);
		return;
	}
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	build(ls,l,mid);build(rs,mid+1,r);
	seg[x]=seg[ls]+seg[rs];
}

void modify(int x,int l,int r,int p,int k){
	if(l==r){
		seg[x].a[1]^=k;mx=max(mx,seg[x].a[1]);
		if(!seg[x].a[1])seg[x].m=0;else seg[x].m=1;
		return;
	}
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	if(p<=mid)modify(ls,l,mid,p,k);
	else modify(rs,mid+1,r,p,k);
	seg[x]=seg[ls]+seg[rs];
}
LinearBase query(int x,int l,int r,int s,int t){
	if(l==s&&r==t)return seg[x];
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	if(t<=mid)return query(ls,l,mid,s,t);
	if(s>mid)return query(rs,mid+1,r,s,t);
	LinearBase w=query(ls,l,mid,s,mid);
	if((1ll<<w.m)>mx)return w;
	return w+query(rs,mid+1,r,mid+1,t);
}

int sum[N];
void add(int x,int u){while(x<=n)sum[x]^=u,x+=lowbit(x);}
int ask(int x){int r=0;while(x)r^=sum[x],x-=lowbit(x);return r;}

int main(){
	gi(n),gi(q);
	for(int i=1,s=0;i<=n;i++)gi(a[i]),add(i,a[i]),add(i+1,a[i]);
	for(int i=n;i>=1;i--)mx=max(mx,a[i]^=a[i-1]);
	build(1,1,n);
	for(int i=1,op,l,r,k;i<=q;i++){
		gi(op);gi(l);gi(r);
		if(op==1){
			gi(k);modify(1,1,n,l,k);
			if(r<n)modify(1,1,n,r+1,k);
			add(l,k);add(r+1,k);
		}else{
			if(l<r)ans=query(1,1,n,l+1,r);else ans.clear();
			ans.ext(ask(l));
			print(1<<ans.m);
			putc('\n');
		}
	}
	io::flush();
	return 0;
}


#include<bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#define mms(a,n) memset(a,0,sizeof((a)[0])*(n))
#define mmp(a,b,n) memcpy(a,b,sizeof((b)[0])*(n))
#define lowbit(x) ((x)&-(x))
#define pb push_back
#define fi first
#define se second
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define lowbit(x) ((x)&-(x))
#define fo(i,l,r) for(register int i=l,_lim_=r;i<=_lim_;i++)
#define fd(i,r,l) for(register int i=r,_lim_=l;i>=_lim_;i--)

using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pi;
typedef double db;
typedef long double ldb;

namespace io{
	const int L=(1<<21)+1;
	char ibuf[L],*iS,*iT,obuf[L],*oS=obuf,*oT=obuf+L-1,c,st[55];int f,tp;
	#ifdef whzzt
		#define gc() getchar()
	#else
		#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,L,stdin),(iS==iT?EOF:*iS++)):*iS++)
	#endif
	inline void flush(){fwrite(obuf,1,oS-obuf,stdout);oS=obuf;}
	inline void putc(char x){*oS++=x;if(oS==oT)flush();}
	template<class I>
	inline void gi(I&x){
		for(f=1,c=gc();c<'0'||c>'9';c=gc())if(c=='-')f=-1;
		for(x=0;c<='9'&&c>='0';c=gc())x=x*10+(c&15);x*=f;
	}
	template<class I>
	inline void print(I x){
		if(!x)putc('0');if(x<0)putc('-'),x=-x;
		while(x)st[++tp]=x%10+'0',x/=10;
		while(tp)putc(st[tp--]);
	}
	inline void gs(char*s,int&l){
		for(c=gc();c!='_'&&(c<'a'||c>'z');c=gc());
		for(l=0;c=='_'||c<='z'&&c>='a';c=gc())s[l++]=c;
	}
};
using io::putc;
using io::gi;
using io::gs;
using io::print;

const int N=200005,M=32,L=525005;

int n,q,a[N],mx;
struct LinearBase{
	int a[M],m;
	int find(int k){
		for(int i=1;i<=m;i++)if((k^a[i])<k)k^=a[i];
		return k;
	}
	void ext(int k){
		if(mx>>m){
			if(k=find(k)){
				int j=1;
				while(k<=a[j])j++;
				++m;for(int i=m;i>j;i--)a[i]=a[i-1];
				a[j]=k;
				for(int i=1;i<j;i++)if((k^a[i])<a[i])a[i]^=k;
			}
		}
	}
	friend LinearBase operator+(const LinearBase&a,const LinearBase&b){
		if((1ll<<a.m)>mx)return a;if((1ll<<b.m)>mx)return b;
		LinearBase ret=a;
		for(int i=1;i<=b.m;i++)ret.ext(b.a[i]);
		return ret;
	}
	void clear(){while(m)a[m--]=0;}
}seg[L],ans;

void build(int x,int l,int r){
	if(l==r){
		seg[x].ext(a[l]);
		return;
	}
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	build(ls,l,mid);build(rs,mid+1,r);
	seg[x]=seg[ls]+seg[rs];
}

void modify(int x,int l,int r,int p,int k){
	if(l==r){
		seg[x].a[1]^=k;
		mx=max(mx,seg[x].a[1]);
		if(!seg[x].a[1])seg[x].m=0;else seg[x].m=1;
		return;
	}
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	if(p<=mid)modify(ls,l,mid,p,k);
	else modify(rs,mid+1,r,p,k);
	seg[x]=seg[ls]+seg[rs];
}
void modify(int x,int l,int r,int p,int q,int k){
	if(l==r){
		seg[x].a[1]^=k;
		mx=max(mx,seg[x].a[1]);
		if(!seg[x].a[1])seg[x].m=0;else seg[x].m=1;
		return;
	}
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	if(q<=mid)modify(ls,l,mid,p,q,k);
	else if(p>mid)modify(rs,mid+1,r,p,q,k);
	else modify(ls,l,mid,p,k),modify(rs,mid+1,r,q,k);
	seg[x]=seg[ls]+seg[rs];
}

LinearBase query(int x,int l,int r,int s,int t){
	if(l==s&&r==t)return seg[x];
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	if(t<=mid)return query(ls,l,mid,s,t);
	if(s>mid)return query(rs,mid+1,r,s,t);
	if(t-mid>=mid-s+1){
		LinearBase w=query(rs,mid+1,r,mid+1,t);
		if((1ll<<w.m)>mx)return w;
		return w+query(ls,l,mid,s,mid);
	}
	LinearBase w=query(ls,l,mid,s,mid);
	if((1ll<<w.m)>mx)return w;
	return w+query(rs,mid+1,r,mid+1,t);
}

int sum[N];
void add(int x,int u){while(x<=n)sum[x]^=u,x+=lowbit(x);}
int ask(int x){int r=0;while(x)r^=sum[x],x-=lowbit(x);return r;}

int main(){
	gi(n),gi(q);
	for(int i=1,s=0;i<=n;i++)gi(a[i]),add(i,a[i]),add(i+1,a[i]);
	for(int i=n;i>=1;i--)mx=max(mx,a[i]^=a[i-1]);
	build(1,1,n);
	for(int i=1,op,l,r,k;i<=q;i++){
		gi(op);gi(l);gi(r);
		if(op==1){
			gi(k);
			if(r<n)modify(1,1,n,l,r+1,k);else modify(1,1,n,l,k);
			add(l,k);add(r+1,k);
		}else{
			if(l<r)ans=query(1,1,n,l+1,r);else ans.clear();
			ans.ext(ask(l));
			print(1<<ans.m);
			putc('\n');
		}
	}
	io::flush();
	return 0;
}


#include<bits/stdc++.h>
#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#define mms(a,n) memset(a,0,sizeof((a)[0])*(n))
#define mmp(a,b,n) memcpy(a,b,sizeof((b)[0])*(n))
#define lowbit(x) ((x)&-(x))
#define pb push_back
#define fi first
#define se second
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define lowbit(x) ((x)&-(x))
#define fo(i,l,r) for(register int i=l,_lim_=r;i<=_lim_;i++)
#define fd(i,r,l) for(register int i=r,_lim_=l;i>=_lim_;i--)

using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pi;
typedef double db;
typedef long double ldb;

namespace io{
	const int L=(1<<21)+1;
	char ibuf[L],*iS,*iT,obuf[L],*oS=obuf,*oT=obuf+L-1,c,st[55];int f,tp;
	#ifdef whzzt
		#define gc() getchar()
	#else
		#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,L,stdin),(iS==iT?EOF:*iS++)):*iS++)
	#endif
	inline void flush(){fwrite(obuf,1,oS-obuf,stdout);oS=obuf;}
	inline void putc(char x){*oS++=x;if(oS==oT)flush();}
	template<class I>
	inline void gi(I&x){
		for(f=1,c=gc();c<'0'||c>'9';c=gc())if(c=='-')f=-1;
		for(x=0;c<='9'&&c>='0';c=gc())x=x*10+(c&15);x*=f;
	}
	template<class I>
	inline void print(I x){
		if(!x)putc('0');if(x<0)putc('-'),x=-x;
		while(x)st[++tp]=x%10+'0',x/=10;
		while(tp)putc(st[tp--]);
	}
	inline void gs(char*s,int&l){
		for(c=gc();c!='_'&&(c<'a'||c>'z');c=gc());
		for(l=0;c=='_'||c<='z'&&c>='a';c=gc())s[l++]=c;
	}
};
using io::putc;
using io::gi;
using io::gs;
using io::print;

const int N=200005,M=32,L=525005;

int n,q,a[N],mx;
struct LinearBase{
	int a[M],m;
	int find(int k){
		for(int i=1;i<=m;i++)if((k^a[i])<k)k^=a[i];
		return k;
	}
	void ext(int k){
		if(k=find(k)){
			int j=1;
			while(k<=a[j])j++;
			++m;for(int i=m;i>j;i--)a[i]=a[i-1];
			a[j]=k;
			for(int i=1;i<j;i++)if((k^a[i])<a[i])a[i]^=k;
		}
	}
	friend LinearBase operator+(const LinearBase&a,const LinearBase&b){
		if((1ll<<a.m)>mx)return a;if((1ll<<b.m)>mx)return b;
		LinearBase ret=a;
		for(int i=1;i<=b.m;i++)ret.ext(b.a[i]);
		return ret;
	}
	void clear(){while(m)a[m--]=0;}
}seg[L],ans;

void build(int x,int l,int r){
	if(l==r){
		seg[x].ext(a[l]);
		return;
	}
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	build(ls,l,mid);build(rs,mid+1,r);
	seg[x]=seg[ls]+seg[rs];
}

void modify(int x,int l,int r,int p,int k){
	if(l==r){
		seg[x].a[1]^=k;
		mx=max(mx,seg[x].a[1]);
		if(!seg[x].a[1])seg[x].m=0;else seg[x].m=1;
		return;
	}
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	if(p<=mid)modify(ls,l,mid,p,k);
	else modify(rs,mid+1,r,p,k);
	seg[x]=seg[ls]+seg[rs];
}
void modify(int x,int l,int r,int p,int q,int k){
	if(l==r){
		seg[x].a[1]^=k;
		mx=max(mx,seg[x].a[1]);
		if(!seg[x].a[1])seg[x].m=0;else seg[x].m=1;
		return;
	}
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	if(q<=mid)modify(ls,l,mid,p,q,k);
	else if(p>mid)modify(rs,mid+1,r,p,q,k);
	else modify(ls,l,mid,p,k),modify(rs,mid+1,r,q,k);
	seg[x]=seg[ls]+seg[rs];
}

void query(int x,int l,int r,int s,int t){
	if((1ll<<ans.m)>mx)return;
	if(l==s&&r==t){
		for(int i=1;i<=seg[x].m;i++){
			ans.ext(seg[x].a[i]);
		}
		return;
	}
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	if(t<=mid)query(ls,l,mid,s,t);
	else if(s>mid)query(rs,mid+1,r,s,t);
	else query(ls,l,mid,s,mid),query(rs,mid+1,r,mid+1,t);
}

int sum[N];
void add(int x,int u){while(x<=n)sum[x]^=u,x+=lowbit(x);}
int ask(int x){int r=0;while(x)r^=sum[x],x-=lowbit(x);return r;}

int main(){
	gi(n),gi(q);
	for(int i=1,s=0;i<=n;i++)gi(a[i]),add(i,a[i]),add(i+1,a[i]);
	for(int i=n;i>=1;i--)mx=max(mx,a[i]^=a[i-1]);
	build(1,1,n);
	for(int i=1,op,l,r,k;i<=q;i++){
		gi(op);gi(l);gi(r);
		if(op==1){
			gi(k);
			if(r<n)modify(1,1,n,l,r+1,k);else modify(1,1,n,l,k);
			add(l,k);add(r+1,k);
		}else{
			ans.clear();
			if(l<r)query(1,1,n,l+1,r);
			ans.ext(ask(l));
			print(1<<ans.m);
			putc('\n');
		}
	}
	io::flush();
	return 0;
}


#include<bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#define mms(a,n) memset(a,0,sizeof((a)[0])*(n))
#define mmp(a,b,n) memcpy(a,b,sizeof((b)[0])*(n))
#define lowbit(x) ((x)&-(x))
#define pb push_back
#define fi first
#define se second
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define lowbit(x) ((x)&-(x))
#define fo(i,l,r) for(register int i=l,_lim_=r;i<=_lim_;i++)
#define fd(i,r,l) for(register int i=r,_lim_=l;i>=_lim_;i--)

using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pi;
typedef double db;
typedef long double ldb;

namespace io{
	const int L=(1<<21)+1;
	char ibuf[L],*iS,*iT,obuf[L],*oS=obuf,*oT=obuf+L-1,c,st[55];int f,tp;
	#ifdef whzzt
		#define gc() getchar()
	#else
		#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,L,stdin),(iS==iT?EOF:*iS++)):*iS++)
	#endif
	inline void flush(){fwrite(obuf,1,oS-obuf,stdout);oS=obuf;}
	inline void putc(char x){*oS++=x;if(oS==oT)flush();}
	template<class I>
	inline void gi(I&x){
		for(f=1,c=gc();c<'0'||c>'9';c=gc())if(c=='-')f=-1;
		for(x=0;c<='9'&&c>='0';c=gc())x=x*10+(c&15);x*=f;
	}
	template<class I>
	inline void print(I x){
		if(!x)putc('0');if(x<0)putc('-'),x=-x;
		while(x)st[++tp]=x%10+'0',x/=10;
		while(tp)putc(st[tp--]);
	}
	inline void gs(char*s,int&l){
		for(c=gc();c!='_'&&(c<'a'||c>'z');c=gc());
		for(l=0;c=='_'||c<='z'&&c>='a';c=gc())s[l++]=c;
	}
};
using io::putc;
using io::gi;
using io::gs;
using io::print;

const int N=200005,M=32,L=525005;

int n,q,a[N],mx;
struct LinearBase{
	int a[M],m;
	int find(int k){
		for(int i=1;i<=m;i++)if((k^a[i])<k)k^=a[i];
		return k;
	}
	void ext(int k){
		if(mx>>k){
			if(k=find(k)){
				int j=1;
				while(k<=a[j])j++;
				++m;for(int i=m;i>j;i--)a[i]=a[i-1];
				a[j]=k;
				for(int i=1;i<j;i++)if((k^a[i])<a[i])a[i]^=k;
			}
		}
	}
	friend LinearBase operator+(const LinearBase&a,const LinearBase&b){
		if((1ll<<a.m)>mx)return a;if((1ll<<b.m)>mx)return b;
		LinearBase ret=a;
		for(int i=1;i<=b.m;i++)ret.ext(b.a[i]);
		return ret;
	}
	void clear(){while(m)a[m--]=0;}
}seg[L],ans;

void build(int x,int l,int r){
	if(l==r){
		seg[x].ext(a[l]);
		return;
	}
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	build(ls,l,mid);build(rs,mid+1,r);
	seg[x]=seg[ls]+seg[rs];
}

void modify(int x,int l,int r,int p,int k){
	if(l==r){
		seg[x].a[1]^=k;
		mx=max(mx,seg[x].a[1]);
		if(!seg[x].a[1])seg[x].m=0;else seg[x].m=1;
		return;
	}
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	if(p<=mid)modify(ls,l,mid,p,k);
	else modify(rs,mid+1,r,p,k);
	seg[x]=seg[ls]+seg[rs];
}
void modify(int x,int l,int r,int p,int q,int k){
	if(l==r){
		seg[x].a[1]^=k;
		mx=max(mx,seg[x].a[1]);
		if(!seg[x].a[1])seg[x].m=0;else seg[x].m=1;
		return;
	}
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	if(q<=mid)modify(ls,l,mid,p,q,k);
	else if(p>mid)modify(rs,mid+1,r,p,q,k);
	else modify(ls,l,mid,p,k),modify(rs,mid+1,r,q,k);
	seg[x]=seg[ls]+seg[rs];
}

LinearBase query(int x,int l,int r,int s,int t){
	if(l==s&&r==t)return seg[x];
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	if(t<=mid)return query(ls,l,mid,s,t);
	if(s>mid)return query(rs,mid+1,r,s,t);
	LinearBase w=query(ls,l,mid,s,mid);
	if((1ll<<w.m)>mx)return w;
	return w+query(rs,mid+1,r,mid+1,t);
}

int sum[N];
void add(int x,int u){while(x<=n)sum[x]^=u,x+=lowbit(x);}
int ask(int x){int r=0;while(x)r^=sum[x],x-=lowbit(x);return r;}

int main(){
	gi(n),gi(q);
	for(int i=1,s=0;i<=n;i++)gi(a[i]),add(i,a[i]),add(i+1,a[i]);
	for(int i=n;i>=1;i--)mx=max(mx,a[i]^=a[i-1]);
	build(1,1,n);
	for(int i=1,op,l,r,k;i<=q;i++){
		gi(op);gi(l);gi(r);
		if(op==1){
			gi(k);
			if(r<n)modify(1,1,n,l,r+1,k);else modify(1,1,n,l,k);
			add(l,k);add(r+1,k);
		}else{
			if(l<r)ans=query(1,1,n,l+1,r);else ans.clear();
			ans.ext(ask(l));
			print(1<<ans.m);
			putc('\n');
		}
	}
	io::flush();
	return 0;
}


#include<bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#define mms(a,n) memset(a,0,sizeof((a)[0])*(n))
#define mmp(a,b,n) memcpy(a,b,sizeof((b)[0])*(n))
#define lowbit(x) ((x)&-(x))
#define pb push_back
#define fi first
#define se second
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define lowbit(x) ((x)&-(x))
#define fo(i,l,r) for(register int i=l,_lim_=r;i<=_lim_;i++)
#define fd(i,r,l) for(register int i=r,_lim_=l;i>=_lim_;i--)

using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pi;
typedef double db;
typedef long double ldb;

namespace io{
	const int L=(1<<21)+1;
	char ibuf[L],*iS,*iT,obuf[L],*oS=obuf,*oT=obuf+L-1,c,st[55];int f,tp;
	#ifdef whzzt
		#define gc() getchar()
	#else
		#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,L,stdin),(iS==iT?EOF:*iS++)):*iS++)
	#endif
	inline void flush(){fwrite(obuf,1,oS-obuf,stdout);oS=obuf;}
	inline void putc(char x){*oS++=x;if(oS==oT)flush();}
	template<class I>
	inline void gi(I&x){
		for(f=1,c=gc();c<'0'||c>'9';c=gc())if(c=='-')f=-1;
		for(x=0;c<='9'&&c>='0';c=gc())x=x*10+(c&15);x*=f;
	}
	template<class I>
	inline void print(I x){
		if(!x)putc('0');if(x<0)putc('-'),x=-x;
		while(x)st[++tp]=x%10+'0',x/=10;
		while(tp)putc(st[tp--]);
	}
	inline void gs(char*s,int&l){
		for(c=gc();c!='_'&&(c<'a'||c>'z');c=gc());
		for(l=0;c=='_'||c<='z'&&c>='a';c=gc())s[l++]=c;
	}
};
using io::putc;
using io::gi;
using io::gs;
using io::print;

const int N=200005,M=32,L=525005;

int n,q,a[N],mx;
struct LinearBase{
	int a[M],m;
	int find(int k){
		for(int i=1;i<=m;i++)if((k^a[i])<k)k^=a[i];
		return k;
	}
	void ext(int k){
		if(k=find(k)){
			int j=1;
			while(k<=a[j])j++;
			++m;for(int i=m;i>j;i--)a[i]=a[i-1];
			a[j]=k;
			for(int i=1;i<j;i++)if((k^a[i])<a[i])a[i]^=k;
		}
	}
	friend LinearBase operator+(const LinearBase&a,const LinearBase&b){
		if((1ll<<a.m)>mx)return a;if((1ll<<b.m)>mx)return b;
		LinearBase ret=a;
		for(int i=1;i<=b.m;i++)ret.ext(b.a[i]);
		return ret;
	}
	void clear(){while(m)a[m--]=0;}
}seg[L],ans;

void build(int x,int l,int r){
	if(l==r){
		seg[x].ext(a[l]);
		return;
	}
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	build(ls,l,mid);build(rs,mid+1,r);
	seg[x]=seg[ls]+seg[rs];
}

void modify(int x,int l,int r,int p,int k){
	if(l==r){
		seg[x].a[1]^=k;
		mx=max(mx,seg[x].a[1]);
		if(!seg[x].a[1])seg[x].m=0;else seg[x].m=1;
		return;
	}
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	if(p<=mid)modify(ls,l,mid,p,k);
	else modify(rs,mid+1,r,p,k);
	seg[x]=seg[ls]+seg[rs];
}
void modify(int x,int l,int r,int p,int q,int k){
	if(l==r){
		seg[x].a[1]^=k;
		mx=max(mx,seg[x].a[1]);
		if(!seg[x].a[1])seg[x].m=0;else seg[x].m=1;
		return;
	}
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	if(q<=mid)modify(ls,l,mid,p,q,k);
	else if(p>mid)modify(rs,mid+1,r,p,q,k);
	else modify(ls,l,mid,p,k),modify(rs,mid+1,r,q,k);
	seg[x]=seg[ls]+seg[rs];
}

void query(int x,int l,int r,int s,int t){
	if((1ll<<ans.m)>mx)return;
	if(l==s&&r==t){
		ans=ans+seg[x];
		return;
	}
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	if(t<=mid)query(ls,l,mid,s,t);
	else if(s>mid)query(rs,mid+1,r,s,t);
	else query(ls,l,mid,s,mid),query(rs,mid+1,r,mid+1,t);
}

int sum[N];
void add(int x,int u){while(x<=n)sum[x]^=u,x+=lowbit(x);}
int ask(int x){int r=0;while(x)r^=sum[x],x-=lowbit(x);return r;}

int main(){
	gi(n),gi(q);
	for(int i=1,s=0;i<=n;i++)gi(a[i]),add(i,a[i]),add(i+1,a[i]);
	for(int i=n;i>=1;i--)mx=max(mx,a[i]^=a[i-1]);
	build(1,1,n);
	for(int i=1,op,l,r,k;i<=q;i++){
		gi(op);gi(l);gi(r);
		if(op==1){
			gi(k);
			if(r<n)modify(1,1,n,l,r+1,k);else modify(1,1,n,l,k);
			add(l,k);add(r+1,k);
		}else{
			ans.clear();
			if(l<r)query(1,1,n,l+1,r);
			ans.ext(ask(l));
			print(1<<ans.m);
			putc('\n');
		}
	}
	io::flush();
	return 0;
}


#include<bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#define mms(a,n) memset(a,0,sizeof((a)[0])*(n))
#define mmp(a,b,n) memcpy(a,b,sizeof((b)[0])*(n))
#define lowbit(x) ((x)&-(x))
#define pb push_back
#define fi first
#define se second
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define lowbit(x) ((x)&-(x))
#define fo(i,l,r) for(register int i=l,_lim_=r;i<=_lim_;i++)
#define fd(i,r,l) for(register int i=r,_lim_=l;i>=_lim_;i--)

using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pi;
typedef double db;
typedef long double ldb;

namespace io{
	const int L=(1<<23)+1;
	char ibuf[L],*iS,*iT,obuf[L],*oS=obuf,*oT=obuf+L-1,c,st[55];int f,tp;
	#ifdef whzzt
		#define gc() getchar()
	#else
		#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,L,stdin),(iS==iT?EOF:*iS++)):*iS++)
	#endif
	inline void flush(){fwrite(obuf,1,oS-obuf,stdout);oS=obuf;}
	inline void putc(char x){*oS++=x;if(oS==oT)flush();}
	template<class I>
	inline void gi(I&x){
		for(f=1,c=gc();c<'0'||c>'9';c=gc())if(c=='-')f=-1;
		for(x=0;c<='9'&&c>='0';c=gc())x=x*10+(c&15);x*=f;
	}
	template<class I>
	inline void print(I x){
		if(!x)putc('0');if(x<0)putc('-'),x=-x;
		while(x)st[++tp]=x%10+'0',x/=10;
		while(tp)putc(st[tp--]);
	}
	inline void gs(char*s,int&l){
		for(c=gc();c!='_'&&(c<'a'||c>'z');c=gc());
		for(l=0;c=='_'||c<='z'&&c>='a';c=gc())s[l++]=c;
	}
};
using io::putc;
using io::gi;
using io::gs;
using io::print;

const int N=200005,M=32,L=525005;

int n,q,a[N],mx;
struct LinearBase{
	int a[M],m;
	int find(int k){
		for(int i=1;i<=m;i++)if((k^a[i])<k){
			k^=a[i];
			if(!k)return k;
		}
		return k;
	}
	void ext(int k){
		if(k=find(k)){
			int j=1;
			while(k<=a[j])j++;
			++m;for(int i=m;i>j;i--)a[i]=a[i-1];
			a[j]=k;
			for(int i=1;i<j;i++)if((k^a[i])<a[i])a[i]^=k;
		}
	}
	friend LinearBase operator+(const LinearBase&a,const LinearBase&b){
		if((1ll<<a.m)>mx)return a;if((1ll<<b.m)>mx)return b;
		LinearBase ret=a;
		for(int i=1;i<=b.m;i++)ret.ext(b.a[i]);
		return ret;
	}
	void clear(){while(m)a[m--]=0;}
}seg[L],ans;

void build(int x,int l,int r){
	if(l==r){
		seg[x].ext(a[l]);
		return;
	}
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	build(ls,l,mid);build(rs,mid+1,r);
	seg[x]=seg[ls]+seg[rs];
}

void modify(int x,int l,int r,int p,int k){
	if(l==r){
		seg[x].a[1]^=k;mx=max(mx,seg[x].a[1]);
		if(!seg[x].a[1])seg[x].m=0;else seg[x].m=1;
		return;
	}
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	if(p<=mid)modify(ls,l,mid,p,k);
	else modify(rs,mid+1,r,p,k);
	seg[x]=seg[ls]+seg[rs];
}
LinearBase query(int x,int l,int r,int s,int t){
	if(l==s&&r==t)return seg[x];
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	if(t<=mid)return query(ls,l,mid,s,t);
	if(s>mid)return query(rs,mid+1,r,s,t);
	LinearBase w=query(ls,l,mid,s,mid);
	if((1ll<<w.m)>mx)return w;
	return w+query(rs,mid+1,r,mid+1,t);
}

int sum[N];
void add(int x,int u){while(x<=n)sum[x]^=u,x+=lowbit(x);}
int ask(int x){int r=0;while(x)r^=sum[x],x-=lowbit(x);return r;}

int main(){
	gi(n),gi(q);
	for(int i=1,s=0;i<=n;i++)gi(a[i]),add(i,a[i]),add(i+1,a[i]);
	for(int i=n;i>=1;i--)mx=max(mx,a[i]^=a[i-1]);
	build(1,1,n);
	for(int i=1,op,l,r,k;i<=q;i++){
		gi(op);gi(l);gi(r);
		if(op==1){
			gi(k);modify(1,1,n,l,k);
			if(r<n)modify(1,1,n,r+1,k);
			add(l,k);add(r+1,k);
		}else{
			if(l<r)ans=query(1,1,n,l+1,r);else ans.clear();
			ans.ext(ask(l));
			print(1<<ans.m);
			putc('\n');
		}
	}
	io::flush();
	return 0;
}


#include<bits/stdc++.h>
#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#define mms(a,n) memset(a,0,sizeof((a)[0])*(n))
#define mmp(a,b,n) memcpy(a,b,sizeof((b)[0])*(n))
#define lowbit(x) ((x)&-(x))
#define pb push_back
#define fi first
#define se second
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define lowbit(x) ((x)&-(x))
#define fo(i,l,r) for(register int i=l,_lim_=r;i<=_lim_;i++)
#define fd(i,r,l) for(register int i=r,_lim_=l;i>=_lim_;i--)

using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pi;
typedef double db;
typedef long double ldb;

namespace io{
	const int L=(1<<21)+1;
	char ibuf[L],*iS,*iT,obuf[L],*oS=obuf,*oT=obuf+L-1,c,st[55];int f,tp;
	#ifdef whzzt
		#define gc() getchar()
	#else
		#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,L,stdin),(iS==iT?EOF:*iS++)):*iS++)
	#endif
	inline void flush(){fwrite(obuf,1,oS-obuf,stdout);oS=obuf;}
	inline void putc(char x){*oS++=x;if(oS==oT)flush();}
	template<class I>
	inline void gi(I&x){
		for(f=1,c=gc();c<'0'||c>'9';c=gc())if(c=='-')f=-1;
		for(x=0;c<='9'&&c>='0';c=gc())x=x*10+(c&15);x*=f;
	}
	template<class I>
	inline void print(I x){
		if(!x)putc('0');if(x<0)putc('-'),x=-x;
		while(x)st[++tp]=x%10+'0',x/=10;
		while(tp)putc(st[tp--]);
	}
	inline void gs(char*s,int&l){
		for(c=gc();c!='_'&&(c<'a'||c>'z');c=gc());
		for(l=0;c=='_'||c<='z'&&c>='a';c=gc())s[l++]=c;
	}
};
using io::putc;
using io::gi;
using io::gs;
using io::print;

const int N=200005,M=32,L=525005;

int n,q,a[N],mx;
struct LinearBase{
	int a[M],m;
	int find(int k){
		for(int i=1;i<=m;i++)if((k^a[i])<k)k^=a[i];
		return k;
	}
	void ext(int k){
		if(k=find(k)){
			int j=1;
			while(k<=a[j])j++;
			++m;for(int i=m;i>j;i--)a[i]=a[i-1];
			a[j]=k;
			for(int i=1;i<j;i++)if((k^a[i])<a[i])a[i]^=k;
		}
	}
	friend LinearBase operator+(const LinearBase&a,const LinearBase&b){
		if((1ll<<a.m)>mx)return a;if((1ll<<b.m)>mx)return b;
		LinearBase ret=a;
		for(int i=1;i<=b.m;i++)ret.ext(b.a[i]);
		return ret;
	}
	void clear(){while(m)a[m--]=0;}
}seg[L],ans;

void build(int x,int l,int r){
	if(l==r){
		seg[x].ext(a[l]);
		return;
	}
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	build(ls,l,mid);build(rs,mid+1,r);
	seg[x]=seg[ls]+seg[rs];
}

void modify(int x,int l,int r,int p,int k){
	if(l==r){
		seg[x].a[1]^=k;
		mx=max(mx,seg[x].a[1]);
		if(!seg[x].a[1])seg[x].m=0;else seg[x].m=1;
		return;
	}
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	if(p<=mid)modify(ls,l,mid,p,k);
	else modify(rs,mid+1,r,p,k);
	seg[x]=seg[ls]+seg[rs];
}
void modify(int x,int l,int r,int p,int q,int k){
	if(l==r){
		seg[x].a[1]^=k;
		mx=max(mx,seg[x].a[1]);
		if(!seg[x].a[1])seg[x].m=0;else seg[x].m=1;
		return;
	}
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	if(q<=mid)modify(ls,l,mid,p,q,k);
	else if(p>mid)modify(rs,mid+1,r,p,q,k);
	else modify(ls,l,mid,p,k),modify(rs,mid+1,r,q,k);
	seg[x]=seg[ls]+seg[rs];
}

void query(int x,int l,int r,int s,int t){
	if(l==s&&r==t){
		for(int i=1;i<=seg[x].m;i++){
			ans.ext(seg[x].a[i]);
			if((1ll<<ans.m)>mx)return;
		}
		return;
	}
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	if(t<=mid)query(ls,l,mid,s,t);
	else if(s>mid)query(rs,mid+1,r,s,t);
	else query(ls,l,mid,s,mid),query(rs,mid+1,r,mid+1,t);
}

int sum[N];
void add(int x,int u){while(x<=n)sum[x]^=u,x+=lowbit(x);}
int ask(int x){int r=0;while(x)r^=sum[x],x-=lowbit(x);return r;}

int main(){
	gi(n),gi(q);
	for(int i=1,s=0;i<=n;i++)gi(a[i]),add(i,a[i]),add(i+1,a[i]);
	for(int i=n;i>=1;i--)mx=max(mx,a[i]^=a[i-1]);
	build(1,1,n);
	for(int i=1,op,l,r,k;i<=q;i++){
		gi(op);gi(l);gi(r);
		if(op==1){
			gi(k);
			if(r<n)modify(1,1,n,l,r+1,k);else modify(1,1,n,l,k);
			add(l,k);add(r+1,k);
		}else{
			ans.clear();
			if(l<r)query(1,1,n,l+1,r);
			ans.ext(ask(l));
			print(1<<ans.m);
			putc('\n');
		}
	}
	io::flush();
	return 0;
}


#include<bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#define mms(a,n) memset(a,0,sizeof((a)[0])*(n))
#define mmp(a,b,n) memcpy(a,b,sizeof((b)[0])*(n))
#define lowbit(x) ((x)&-(x))
#define pb push_back
#define fi first
#define se second
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define lowbit(x) ((x)&-(x))
#define fo(i,l,r) for(register int i=l,_lim_=r;i<=_lim_;i++)
#define fd(i,r,l) for(register int i=r,_lim_=l;i>=_lim_;i--)

using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pi;
typedef double db;
typedef long double ldb;

namespace io{
	const int L=(1<<21)+1;
	char ibuf[L],*iS,*iT,obuf[L],*oS=obuf,*oT=obuf+L-1,c,st[55];int f,tp;
	#ifdef whzzt
		#define gc() getchar()
	#else
		#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,L,stdin),(iS==iT?EOF:*iS++)):*iS++)
	#endif
	inline void flush(){fwrite(obuf,1,oS-obuf,stdout);oS=obuf;}
	inline void putc(char x){*oS++=x;if(oS==oT)flush();}
	template<class I>
	inline void gi(I&x){
		for(f=1,c=gc();c<'0'||c>'9';c=gc())if(c=='-')f=-1;
		for(x=0;c<='9'&&c>='0';c=gc())x=x*10+(c&15);x*=f;
	}
	template<class I>
	inline void print(I x){
		if(!x)putc('0');if(x<0)putc('-'),x=-x;
		while(x)st[++tp]=x%10+'0',x/=10;
		while(tp)putc(st[tp--]);
	}
	inline void gs(char*s,int&l){
		for(c=gc();c!='_'&&(c<'a'||c>'z');c=gc());
		for(l=0;c=='_'||c<='z'&&c>='a';c=gc())s[l++]=c;
	}
};
using io::putc;
using io::gi;
using io::gs;
using io::print;

const int N=200005,M=32,L=525005;

int n,q,a[N],mx;
struct LinearBase{
	int a[M],m;
	int find(int k){
		for(int i=1;i<=m;i++)if((k^a[i])<k)k^=a[i];
		return k;
	}
	void ext(int k){
		if(k=find(k)){
			int j=1;
			while(k<=a[j])j++;
			++m;for(int i=m;i>j;i--)a[i]=a[i-1];
			a[j]=k;
			for(int i=1;i<j;i++)if((k^a[i])<a[i])a[i]^=k;
		}
	}
	friend LinearBase operator+(const LinearBase&a,const LinearBase&b){
		if((1ll<<a.m)>mx)return a;if((1ll<<b.m)>mx)return b;
		LinearBase ret=a;
		for(int i=1;i<=b.m;i++)ret.ext(b.a[i]);
		return ret;
	}
	void clear(){while(m)a[m--]=0;}
}seg[L],ans;

void build(int x,int l,int r){
	if(l==r){
		seg[x].ext(a[l]);
		return;
	}
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	build(ls,l,mid);build(rs,mid+1,r);
	seg[x]=seg[ls]+seg[rs];
}

void modify(int x,int l,int r,int p,int k){
	if(l==r){
		seg[x].a[1]^=k;
		mx=max(mx,seg[x].a[1]);
		if(!seg[x].a[1])seg[x].m=0;else seg[x].m=1;
		return;
	}
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	if(p<=mid)modify(ls,l,mid,p,k);
	else modify(rs,mid+1,r,p,k);
	seg[x]=seg[ls]+seg[rs];
}
void modify(int x,int l,int r,int p,int q,int k){
	if(l==r){
		seg[x].a[1]^=k;
		mx=max(mx,seg[x].a[1]);
		if(!seg[x].a[1])seg[x].m=0;else seg[x].m=1;
		return;
	}
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	if(q<=mid)modify(ls,l,mid,p,q,k);
	else if(p>mid)modify(rs,mid+1,r,p,q,k);
	else modify(ls,l,mid,p,k),modify(rs,mid+1,r,q,k);
	seg[x]=seg[ls]+seg[rs];
}

LinearBase query(int x,int l,int r,int s,int t){
	if(l==s&&r==t)return seg[x];
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	if(t<=mid)return query(ls,l,mid,s,t);
	if(s>mid)return query(rs,mid+1,r,s,t);
	LinearBase w=query(ls,l,mid,s,mid);
	if((1ll<<w.m)>mx)return w;
	return w+query(rs,mid+1,r,mid+1,t);
}

int sum[N];
void add(int x,int u){while(x<=n)sum[x]^=u,x+=lowbit(x);}
int ask(int x){int r=0;while(x)r^=sum[x],x-=lowbit(x);return r;}

int main(){
	gi(n),gi(q);
	for(int i=1,s=0;i<=n;i++)gi(a[i]),add(i,a[i]),add(i+1,a[i]);
	for(int i=n;i>=1;i--)mx=max(mx,a[i]^=a[i-1]);
	build(1,1,n);
	for(int i=1,op,l,r,k;i<=q;i++){
		gi(op);gi(l);gi(r);
		if(op==1){
			gi(k);
			if(r<n)modify(1,1,n,l,r+1,k);else modify(1,1,n,l,k);
			add(l,k);add(r+1,k);
		}else{
			if(l<r)ans=query(1,1,n,l+1,r);else ans.clear();
			ans.ext(ask(l));
			print(1<<ans.m);
			putc('\n');
		}
	}
	io::flush();
	return 0;
}


#include<bits/stdc++.h>
//#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#define mms(a,n) memset(a,0,sizeof((a)[0])*(n))
#define mmp(a,b,n) memcpy(a,b,sizeof((b)[0])*(n))
#define lowbit(x) ((x)&-(x))
#define pb push_back
#define fi first
#define se second
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define lowbit(x) ((x)&-(x))
#define fo(i,l,r) for(register int i=l,_lim_=r;i<=_lim_;i++)
#define fd(i,r,l) for(register int i=r,_lim_=l;i>=_lim_;i--)

using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pi;
typedef double db;
typedef long double ldb;

namespace io{
	const int L=(1<<21)+1;
	char ibuf[L],*iS,*iT,obuf[L],*oS=obuf,*oT=obuf+L-1,c,st[55];int f,tp;
	#ifdef whzzt
		#define gc() getchar()
	#else
		#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,L,stdin),(iS==iT?EOF:*iS++)):*iS++)
	#endif
	inline void flush(){fwrite(obuf,1,oS-obuf,stdout);oS=obuf;}
	inline void putc(char x){*oS++=x;if(oS==oT)flush();}
	template<class I>
	inline void gi(I&x){
		for(f=1,c=gc();c<'0'||c>'9';c=gc())if(c=='-')f=-1;
		for(x=0;c<='9'&&c>='0';c=gc())x=x*10+(c&15);x*=f;
	}
	template<class I>
	inline void print(I x){
		if(!x)putc('0');if(x<0)putc('-'),x=-x;
		while(x)st[++tp]=x%10+'0',x/=10;
		while(tp)putc(st[tp--]);
	}
	inline void gs(char*s,int&l){
		for(c=gc();c!='_'&&(c<'a'||c>'z');c=gc());
		for(l=0;c=='_'||c<='z'&&c>='a';c=gc())s[l++]=c;
	}
};
using io::putc;
using io::gi;
using io::gs;
using io::print;

const int N=200005,M=32,L=525005;

int n,q,a[N],mx;
struct LinearBase{
	int a[M],m;
	int find(int k){
		for(int i=1;i<=m;i++)if((k^a[i])<k)k^=a[i];
		return k;
	}
	void ext(int k){
		if(k=find(k)){
			int j=1;
			while(k<=a[j])j++;
			++m;for(int i=m;i>j;i--)a[i]=a[i-1];
			a[j]=k;
			for(int i=1;i<j;i++)if((k^a[i])<a[i])a[i]^=k;
		}
	}
	friend LinearBase operator+(const LinearBase&a,const LinearBase&b){
		if((1ll<<a.m)>mx)return a;if((1ll<<b.m)>mx)return b;
		LinearBase ret=a;
		for(int i=1;i<=b.m;i++)ret.ext(b.a[i]);
		return ret;
	}
	void clear(){while(m)a[m--]=0;}
}seg[L],ans;

void build(int x,int l,int r){
	if(l==r){
		seg[x].ext(a[l]);
		return;
	}
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	build(ls,l,mid);build(rs,mid+1,r);
	seg[x]=seg[ls]+seg[rs];
}

void modify(int x,int l,int r,int p,int k){
	if(l==r){
		seg[x].a[1]^=k;mx=max(mx,seg[x].a[1]);
		if(!seg[x].a[1])seg[x].m=0;else seg[x].m=1;
		return;
	}
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	if(p<=mid)modify(ls,l,mid,p,k);
	else modify(rs,mid+1,r,p,k);
	seg[x]=seg[ls]+seg[rs];
}
LinearBase query(int x,int l,int r,int s,int t){
	if(l==s&&r==t)return seg[x];
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	if(t<=mid)return query(ls,l,mid,s,t);
	if(s>mid)return query(rs,mid+1,r,s,t);
	LinearBase w=query(ls,l,mid,s,mid);
	if((1ll<<w.m)>mx)return w;
	return w+query(rs,mid+1,r,mid+1,t);
}

int sum[N];
void add(int x,int u){while(x<=n)sum[x]^=u,x+=lowbit(x);}
int ask(int x){int r=0;while(x)r^=sum[x],x-=lowbit(x);return r;}

int main(){
	gi(n),gi(q);
	for(int i=1,s=0;i<=n;i++)gi(a[i]),add(i,a[i]),add(i+1,a[i]);
	for(int i=n;i>=1;i--)mx=max(mx,a[i]^=a[i-1]);
	build(1,1,n);
	for(int i=1,op,l,r,k;i<=q;i++){
		gi(op);gi(l);gi(r);
		if(op==1){
			gi(k);modify(1,1,n,l,k);
			if(r<n)modify(1,1,n,r+1,k);
			add(l,k);add(r+1,k);
		}else{
			if(l<r)ans=query(1,1,n,l+1,r);else ans.clear();
			ans.ext(ask(l));
			print(1<<ans.m);
			putc('\n');
		}
	}
	io::flush();
	return 0;
}


#include<bits/stdc++.h>
//#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#define mms(a,n) memset(a,0,sizeof((a)[0])*(n))
#define mmp(a,b,n) memcpy(a,b,sizeof((b)[0])*(n))
#define lowbit(x) ((x)&-(x))
#define pb push_back
#define fi first
#define se second
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define lowbit(x) ((x)&-(x))
#define fo(i,l,r) for(register int i=l,_lim_=r;i<=_lim_;i++)
#define fd(i,r,l) for(register int i=r,_lim_=l;i>=_lim_;i--)

using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pi;
typedef double db;
typedef long double ldb;

namespace io{
	const int L=(1<<21)+1;
	char ibuf[L],*iS,*iT,obuf[L],*oS=obuf,*oT=obuf+L-1,c,st[55];int f,tp;
	#ifdef whzzt
		#define gc() getchar()
	#else
		#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,L,stdin),(iS==iT?EOF:*iS++)):*iS++)
	#endif
	inline void flush(){fwrite(obuf,1,oS-obuf,stdout);oS=obuf;}
	inline void putc(char x){*oS++=x;if(oS==oT)flush();}
	template<class I>
	inline void gi(I&x){
		for(f=1,c=gc();c<'0'||c>'9';c=gc())if(c=='-')f=-1;
		for(x=0;c<='9'&&c>='0';c=gc())x=x*10+(c&15);x*=f;
	}
	template<class I>
	inline void print(I x){
		if(!x)putc('0');if(x<0)putc('-'),x=-x;
		while(x)st[++tp]=x%10+'0',x/=10;
		while(tp)putc(st[tp--]);
	}
	inline void gs(char*s,int&l){
		for(c=gc();c!='_'&&(c<'a'||c>'z');c=gc());
		for(l=0;c=='_'||c<='z'&&c>='a';c=gc())s[l++]=c;
	}
};
using io::putc;
using io::gi;
using io::gs;
using io::print;

const int N=200005,M=32,L=525005;

int n,q,a[N],mx;
struct LinearBase{
	int a[M],m;
	int find(int k){
		for(int i=1;i<=m;i++)if((k^a[i])<k){
			k^=a[i];
			if(!k)return k;
		}
		return k;
	}
	void ext(int k){
		if(k=find(k)){
			int j=1;
			while(k<=a[j])j++;
			++m;for(int i=m;i>j;i--)a[i]=a[i-1];
			a[j]=k;
			for(int i=1;i<j;i++)if((k^a[i])<a[i])a[i]^=k;
		}
	}
	friend LinearBase operator+(const LinearBase&a,const LinearBase&b){
		if((1ll<<a.m)>mx)return a;if((1ll<<b.m)>mx)return b;
		LinearBase ret=a;
		for(int i=1;i<=b.m;i++)ret.ext(b.a[i]);
		return ret;
	}
	void clear(){while(m)a[m--]=0;}
}seg[L],ans;

void build(int x,int l,int r){
	if(l==r){
		seg[x].ext(a[l]);
		return;
	}
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	build(ls,l,mid);build(rs,mid+1,r);
	seg[x]=seg[ls]+seg[rs];
}

void modify(int x,int l,int r,int p,int k){
	if(l==r){
		seg[x].a[1]^=k;mx=max(mx,seg[x].a[1]);
		if(!seg[x].a[1])seg[x].m=0;else seg[x].m=1;
		return;
	}
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	if(p<=mid)modify(ls,l,mid,p,k);
	else modify(rs,mid+1,r,p,k);
	seg[x]=seg[ls]+seg[rs];
}
LinearBase query(int x,int l,int r,int s,int t){
	if(l==s&&r==t)return seg[x];
	int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
	if(t<=mid)return query(ls,l,mid,s,t);
	if(s>mid)return query(rs,mid+1,r,s,t);
	LinearBase w=query(ls,l,mid,s,mid);
	if((1ll<<w.m)>mx)return w;
	return w+query(rs,mid+1,r,mid+1,t);
}

int sum[N];
void add(int x,int u){while(x<=n)sum[x]^=u,x+=lowbit(x);}
int ask(int x){int r=0;while(x)r^=sum[x],x-=lowbit(x);return r;}

int main(){
	gi(n),gi(q);
	for(int i=1,s=0;i<=n;i++)gi(a[i]),add(i,a[i]),add(i+1,a[i]);
	for(int i=n;i>=1;i--)mx=max(mx,a[i]^=a[i-1]);
	build(1,1,n);
	for(int i=1,op,l,r,k;i<=q;i++){
		gi(op);gi(l);gi(r);
		if(op==1){
			gi(k);modify(1,1,n,l,k);
			if(r<n)modify(1,1,n,r+1,k);
			add(l,k);add(r+1,k);
		}else{
			if(l<r)ans=query(1,1,n,l+1,r);else ans.clear();
			ans.ext(ask(l));
			print(1<<ans.m);
			putc('\n');
		}
	}
	io::flush();
	return 0;
}