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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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


//https://codeforces.com/problemset/problem/587/E

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

typedef vector<int> vi;
typedef vector<vector<int>> vvi;
typedef vector<vector<vector<int>>> vvvi;
typedef pair<int,int> ii;
typedef vector<ii> vii;
typedef vector<vector<ii>> vvii;
typedef vector<vector<vector<ii>>> vvvii;

typedef vector<double> vd;
typedef vector<vector<double>> vvd;
typedef long long ll;
typedef vector<ll> vll;
typedef vector<vector<ll>> vvll;

#define FORI(n) for (int i=0;i<(n);i++)
#define FORJ(n) for (int j=0;j<(n);j++)
#define FORK(n) for (int k=0;k<(n);k++)
#define MOD 1000000007
#define POS_MOD(n,M) (n)%(M) < 0 ? (n)%(M) + (M) : (n)%(M)
#pragma endregion

template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v)
{
    os << "[";
    for (int i = 0; i < v.size(); ++i) {
        os << v[i];
        if (i != v.size() - 1)
            os << ", ";
    }
    os << "]\n";
    return os;
}

void insert(vi& base, int vector){
    for (int k=31;k>=0;k--){
            if ((vector&(1<<k)) && base[k]) vector^=base[k];
            else if ((vector&(1<<k)) && !base[k]){base[k]=vector; break;}
    }
}

int n;
vvi ST_B;
vi ST_X;

void xor_upd(int i, int x, int y, int a, int b, int val){
    if (b<x || a>y) return;
    else if (a<=x && y<=b){
        ST_X[i]^=val; return;
    }
    else{
        int mid=(x+y)/2;
        xor_upd(2*i,x,mid,a,b,val);
        xor_upd(2*i+1,mid+1,y,a,b,val);
    }
}

int xor_q(int i, int x, int y, int tar){
    if (x==y) return ST_X[i];
    else{
        int mid=(x+y)/2;
        if (tar<=mid){
            return ST_X[i]^xor_q(2*i,x,mid,tar);
        }
        else{
            return ST_X[i]^xor_q(2*i+1,mid+1,y,tar);
        }
    }
}

vi base_q(int i, int x, int y, int a, int b){
    if (x>b || y<a) return vi(32);
    else if (a<=x && y<=b){
        return ST_B[i];
    }
    else{
        int mid=(x+y)/2;
        vi bq1=base_q(2*i,x,mid,a,b);
        vi bq2=base_q(2*i+1,mid+1,y,a,b);
        for (int v:bq2) insert(bq1,v);
        if (mid>=a && mid+1<=b) insert(bq1,xor_q(1,0,n-1,mid)^xor_q(1,0,n-1,mid+1));
        return bq1;
    }
}

void base_upd(int i, int x, int y, int a, int b){
    if (x>b || y<a) return;
    else if (a<=x && y<=b){
        return;
    }
    else{
        int mid=(x+y)/2;

        base_upd(2*i,x,mid,a,b); vi res=ST_B[2*i];
        base_upd(2*i+1,mid+1,y,a,b); vi r2=ST_B[2*i+1];
        for (int j:r2) insert(res,j);
        insert(res,xor_q(1,0,n-1,mid)^xor_q(1,0,n-1,mid+1));
        ST_B[i]=res;
    }
}

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

    int q;
    cin>>n>>q;
    ST_B=vvi(4*n,vi(32));
    ST_X=vi(4*n);

    FORI(n){
        int a; cin>>a;
        xor_upd(1,0,n-1,i,i,a);
        base_upd(1,0,n-1,i,i);
        //cout << ST_B << endl;
    }

    while (q--){
        int t; cin>>t;
        if (t==1){
            //xor
            int l,r,k; cin>>l>>r>>k; l--; r--;
            xor_upd(1,0,n-1,l,r,k);
            base_upd(1,0,n-1,l,r);
        }
        else{
            int l,r; cin>>l>>r; l--; r--;
            vi res = base_q(1,0,n-1,l,r);
            int last = xor_q(1,0,n-1,l);
            insert(res,last);

            int pow=1;
            FORI(res.size()) if (res[i]) pow*=2;
            cout << pow << endl;
        }
    }

}


//https://codeforces.com/problemset/problem/587/E

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

typedef vector<int> vi;
typedef vector<vector<int>> vvi;
typedef vector<vector<vector<int>>> vvvi;
typedef pair<int,int> ii;
typedef vector<ii> vii;
typedef vector<vector<ii>> vvii;
typedef vector<vector<vector<ii>>> vvvii;

typedef vector<double> vd;
typedef vector<vector<double>> vvd;
typedef long long ll;
typedef vector<ll> vll;
typedef vector<vector<ll>> vvll;

#define FORI(n) for (int i=0;i<(n);i++)
#define FORJ(n) for (int j=0;j<(n);j++)
#define FORK(n) for (int k=0;k<(n);k++)
#define MOD 1000000007
#define POS_MOD(n,M) (n)%(M) < 0 ? (n)%(M) + (M) : (n)%(M)
#pragma endregion

template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v)
{
    os << "[";
    for (int i = 0; i < v.size(); ++i) {
        os << v[i];
        if (i != v.size() - 1)
            os << ", ";
    }
    os << "]\n";
    return os;
}

void insert(vi& base, int vector){
    for (int k=31;k>=0;k--){
            if ((vector&(1<<k)) && base[k]) vector^=base[k];
            else if ((vector&(1<<k)) && !base[k]){base[k]=vector; break;}
    }
}

int n;
vvi ST_B;
vi ST_X;

void xor_upd(int i, int x, int y, int a, int b, int val){
    if (b<x || a>y) return;
    else if (a<=x && y<=b){
        ST_X[i]^=val; return;
    }
    else{
        int mid=(x+y)/2;
        xor_upd(2*i,x,mid,a,b,val);
        xor_upd(2*i+1,mid+1,y,a,b,val);
    }
}

int xor_q(int i, int x, int y, int tar){
    if (x==y) return ST_X[i];
    else{
        int mid=(x+y)/2;
        if (tar<=mid){
            return ST_X[i]^xor_q(2*i,x,mid,tar);
        }
        else{
            return ST_X[i]^xor_q(2*i+1,mid+1,y,tar);
        }
    }
}

vi base_q(int i, int x, int y, int a, int b){
    if (x>b || y<a) return vi(32);
    else if (a<=x && y<=b){
        return ST_B[i];
    }
    else{
        int mid=(x+y)/2;
        vi bq1=base_q(2*i,x,mid,a,b);
        vi bq2=base_q(2*i+1,mid+1,y,a,b);
        for (int v:bq2) insert(bq1,v);
        return bq1;
    }
}

void base_upd(int i, int x, int y, int a, int b){
    if (x>b || y<a) return;
    else if (a<=x && y<=b){
        return;
    }
    else{
        int mid=(x+y)/2;
        base_upd(2*i,x,mid,a,b);
        base_upd(2*i+1,mid+1,y,a,b);

        base_upd(2*i,x,mid,a,b); vi res=ST_B[2*i];
        base_upd(2*i+1,mid+1,y,a,b); vi r2=ST_B[2*i+1];
        for (int j:r2) insert(res,j);
        insert(res,xor_q(1,0,n-1,mid)^xor_q(1,0,n-1,mid+1));
        ST_B[i]=res;
    }
}

int main(){
    //ios_base::sync_with_stdio(false);
    //cin.tie(NULL);

    int q;
    cin>>n>>q;
    ST_B=vvi(4*n,vi(32));
    ST_X=vi(4*n);

    FORI(n){
        int a; cin>>a;
        xor_upd(1,0,n-1,i,i,a);
        base_upd(1,0,n-1,i,i);
        //cout << ST_B << endl;
    }

    while (q--){
        int t; cin>>t;
        if (t==1){
            //xor
            int l,r,k; cin>>l>>r>>k; l--; r--;
            xor_upd(1,0,n-1,l,r,k);
            base_upd(1,0,n-1,l,r);
        }
        else{
            int l,r; cin>>l>>r; l--; r--;
            vi res = base_q(1,0,n-1,l,r);
            int last = xor_q(1,0,n-1,l);
            insert(res,last);

            int pow=1;
            FORI(res.size()) if (res[i]) pow*=2;
            cout << pow << endl;
        }
    }

}


//https://codeforces.com/problemset/problem/587/E

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

typedef vector<int> vi;
typedef vector<vector<int>> vvi;
typedef vector<vector<vector<int>>> vvvi;
typedef pair<int,int> ii;
typedef vector<ii> vii;
typedef vector<vector<ii>> vvii;
typedef vector<vector<vector<ii>>> vvvii;

typedef vector<double> vd;
typedef vector<vector<double>> vvd;
typedef long long ll;
typedef vector<ll> vll;
typedef vector<vector<ll>> vvll;

#define FORI(n) for (int i=0;i<(n);i++)
#define FORJ(n) for (int j=0;j<(n);j++)
#define FORK(n) for (int k=0;k<(n);k++)
#define MOD 1000000007
#define POS_MOD(n,M) (n)%(M) < 0 ? (n)%(M) + (M) : (n)%(M)
#pragma endregion

void insert(vi& base, int vector){
    if (!vector) return;
    for (int k=31;k>=0;k--){
            if ((vector&(1<<k)) && base[k]) vector^=base[k];
            else if ((vector&(1<<k)) && !base[k]){base[k]=vector; break;}
    }
}

int n;
vvi ST_B;
vi ST_X;

void xor_upd(int i, int x, int y, int a, int b, int val){
    if (b<x || a>y) return;
    else if (a<=x && y<=b){
        ST_X[i]^=val; return;
    }
    else{
        int mid=(x+y)/2;
        xor_upd(2*i,x,mid,a,b,val);
        xor_upd(2*i+1,mid+1,y,a,b,val);
    }
}

int xor_q(int i, int x, int y, int tar){
    if (x==y) return ST_X[i];
    else{
        int mid=(x+y)/2;
        if (tar<=mid){
            return ST_X[i]^xor_q(2*i,x,mid,tar);
        }
        else{
            return ST_X[i]^xor_q(2*i+1,mid+1,y,tar);
        }
    }
}

vi base_q(int i, int x, int y, int a, int b){
    if (x>b || y<a) return vi(32);
    else if (a<=x && y<=b){
        return ST_B[i];
    }
    else{
        int mid=(x+y)/2;
        vi bq1=base_q(2*i,x,mid,a,b);
        vi bq2=base_q(2*i+1,mid+1,y,a,b);
        for (int v:bq2) insert(bq1,v);
        if (mid>=a && mid+1<=b) insert(bq1,xor_q(1,0,n-1,mid)^xor_q(1,0,n-1,mid+1));
        return bq1;
    }
}

void base_upd(int i, int x, int y, int a, int b){
    if (x>b || y<a) return;
    else if (a<=x && y<=b){
        return;
    }
    else{
        int mid=(x+y)/2;

        base_upd(2*i,x,mid,a,b); vi res=ST_B[2*i];
        base_upd(2*i+1,mid+1,y,a,b); vi r2=ST_B[2*i+1];
        for (int j:r2) insert(res,j);
        insert(res,xor_q(1,0,n-1,mid)^xor_q(1,0,n-1,mid+1));
        ST_B[i]=res;
    }
}

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

    int q;
    cin>>n>>q;
    ST_B=vvi(4*n,vi(32));
    ST_X=vi(4*n);

    FORI(n){
        int a; cin>>a;
        xor_upd(1,0,n-1,i,i,a);
        base_upd(1,0,n-1,i,i);
        //cout << ST_B << endl;
    }

    while (q--){
        int t; cin>>t;
        if (t==1){
            //xor
            int l,r,k; cin>>l>>r>>k; l--; r--;
            xor_upd(1,0,n-1,l,r,k);
            base_upd(1,0,n-1,l,r);
        }
        else{
            int l,r; cin>>l>>r; l--; r--;
            vi res = base_q(1,0,n-1,l,r);
            int last = xor_q(1,0,n-1,l);
            insert(res,last);

            int pow=1;
            FORI(res.size()) if (res[i]) pow*=2;
            cout << pow << endl;
        }
    }

}


//https://codeforces.com/problemset/problem/587/E

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

typedef vector<int> vi;
typedef vector<vector<int>> vvi;
typedef vector<vector<vector<int>>> vvvi;
typedef pair<int,int> ii;
typedef vector<ii> vii;
typedef vector<vector<ii>> vvii;
typedef vector<vector<vector<ii>>> vvvii;

typedef vector<double> vd;
typedef vector<vector<double>> vvd;
typedef long long ll;
typedef vector<ll> vll;
typedef vector<vector<ll>> vvll;

#define FORI(n) for (int i=0;i<(n);i++)
#define FORJ(n) for (int j=0;j<(n);j++)
#define FORK(n) for (int k=0;k<(n);k++)
#define MOD 1000000007
#define POS_MOD(n,M) (n)%(M) < 0 ? (n)%(M) + (M) : (n)%(M)
#pragma endregion

template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v)
{
    os << "[";
    for (int i = 0; i < v.size(); ++i) {
        os << v[i];
        if (i != v.size() - 1)
            os << ", ";
    }
    os << "]\n";
    return os;
}

void insert(vi& base, int vector){
    for (int k=31;k>=0;k--){
            if ((vector&(1<<k)) && base[k]) vector^=base[k];
            else if ((vector&(1<<k)) && !base[k]){base[k]=vector; break;}
    }
}

int n;
vvi ST_B;
vi ST_X;

void xor_upd(int i, int x, int y, int a, int b, int val){
    if (b<x || a>y) return;
    else if (a<=x && y<=b){
        ST_X[i]^=val; return;
    }
    else{
        int mid=(x+y)/2;
        xor_upd(2*i,x,mid,a,b,val);
        xor_upd(2*i+1,mid+1,y,a,b,val);
    }
}

int xor_q(int i, int x, int y, int tar){
    if (x==y) return ST_X[i];
    else{
        int mid=(x+y)/2;
        if (tar<=mid){
            return ST_X[i]^xor_q(2*i,x,mid,tar);
        }
        else{
            return ST_X[i]^xor_q(2*i+1,mid+1,y,tar);
        }
    }
}

vi base_q(int i, int x, int y, int a, int b){
    if (x>b || y<a) return vi(32);
    else if (a<=x && y<=b){
        return ST_B[i];
    }
    else{
        int mid=(x+y)/2;
        vi bq1=base_q(2*i,x,mid,a,b);
        vi bq2=base_q(2*i+1,mid+1,y,a,b);
        for (int v:bq2) insert(bq1,v);
        if (mid>=a && mid+1<=b) insert(bq1,xor_q(1,0,n-1,mid)^xor_q(1,0,n-1,mid+1));
        return bq1;
    }
}

void base_upd(int i, int x, int y, int a, int b){
    if (x>b || y<a) return;
    else if (a<=x && y<=b){
        return;
    }
    else{
        int mid=(x+y)/2;

        base_upd(2*i,x,mid,a,b); vi res=ST_B[2*i];
        base_upd(2*i+1,mid+1,y,a,b); vi r2=ST_B[2*i+1];
        for (int j:r2) insert(res,j);
        insert(res,xor_q(1,0,n-1,mid)^xor_q(1,0,n-1,mid+1));
        ST_B[i]=res;
    }
}

int main(){
    //ios_base::sync_with_stdio(false);
    //cin.tie(NULL);

    int q;
    cin>>n>>q;
    ST_B=vvi(4*n,vi(32));
    ST_X=vi(4*n);

    FORI(n){
        int a; cin>>a;
        xor_upd(1,0,n-1,i,i,a);
        base_upd(1,0,n-1,i,i);
        //cout << ST_B << endl;
    }

    while (q--){
        int t; cin>>t;
        if (t==1){
            //xor
            int l,r,k; cin>>l>>r>>k; l--; r--;
            xor_upd(1,0,n-1,l,r,k);
            base_upd(1,0,n-1,l,r);
        }
        else{
            int l,r; cin>>l>>r; l--; r--;
            vi res = base_q(1,0,n-1,l,r);
            int last = xor_q(1,0,n-1,l);
            insert(res,last);

            int pow=1;
            FORI(res.size()) if (res[i]) pow*=2;
            cout << pow << endl;
        }
    }

}


#include <bits/stdc++.h>
using namespace std;
typedef unsigned int uint;
typedef vector<pair<uint, uint>> item;
int const N = 200800;
int const maxc = 33;

item bs[4 * N];
int a[N];
int bit[N];

void bit_modify(int i, uint what) {
    for (++i; i < N; i += i & -i) {
        bit[i] ^= what;
    }
}

uint get_a(int i) {
    uint res = 0;
    for (++i; i > 0; i &= i - 1) {
        res ^= bit[i];
    }
    return res;
}

void add(item& a, item const& b) {
    for (auto x : b) {
        auto num = x.first;
        for (auto& p : a)
            if ((num >> p.second) & 1)
                num ^= p.first;
        if (num) {
            uint f = 0;
            while (!((num >> f) & 1))
                ++f;
            a.emplace_back(num, f);
        }
    }
}

void add(item& a, uint what) {
    add(a, {make_pair(what, -1)});
}

void update(int v) {
    bs[v] = bs[2 * v + 1];
    add(bs[v], bs[2 * v + 2]);
}

void build(int v, int l, int r) {
    bs[v].clear();
    bs[v].reserve(maxc);
    if (r - l > 1) {
        int m = (l + r) / 2;
        build(2 * v + 1, l, m);
        build(2 * v + 2, m, r);
        update(v);
    } else {
        uint val = l ? (a[l] ^ a[l - 1]) : a[l];
        add(bs[v], val);
        bit_modify(l, val);
    }
}

void modify(int v, int l, int r, int pos, uint what) {
    if (r - l == 1) {
        uint val = (bs[v].empty() ? 0 : bs[v][0].first) ^ what;
        bs[v].clear();
        add(bs[v], val);
        bit_modify(l, what);
    } else {
        int m = (l + r) / 2;
        if (pos < m) {
            modify(2 * v + 1, l, m, pos, what);
        } else {
            modify(2 * v + 2, m, r, pos, what);
        }
        update(v);
    }
}

item result;
void basis(int v, int l, int r, int from, int to) {
    if (r <= from || to <= l)
        return;
    if (from <= l && r <= to) {
        add(result, bs[v]);
        return;
    }
    int m = (l + r) / 2;
    basis(2 * v + 1, l, m, from, to);
    basis(2 * v + 2, m, r, from, to);
}

int main() {
    int n, q;
    scanf("%d%d", &n, &q);
    for (int i = 0; i < n; ++i)
        scanf("%d", a + i);
    build(0, 0, n);
    result.reserve(maxc);
    for (int it = 0; it < q; ++it) {
        int type, l, r;
        scanf("%d%d%d", &type, &l, &r);
        --l;
        if (type == 1) {
            int k;
            scanf("%d", &k);
            modify(0, 0, n, l, k);
            modify(0, 0, n, r, k);
        } else {
            result.clear();
            basis(0, 0, n, l + 1, r);
            int val = get_a(l);
            add(result, val);
            cout << (1LL << result.size()) << '\n';
        }
    }
}


#include <bits/stdc++.h>
using namespace std;
typedef unsigned int uint;
typedef vector<uint> item;
int const N = 200800;
int const maxc = 33;

item bs[4 * N];
int a[N];
uint bit[N];

void bit_modify(int i, uint what) {
    for (++i; i < N; i += i & -i) {
        bit[i] ^= what;
    }
}

uint get_a(int i) {
    uint res = 0;
    for (++i; i > 0; i &= i - 1) {
        res ^= bit[i];
    }
    return res;
}

void add(item& a, item const& b) {
    for (auto x : b) {
        for (auto p : a)
            if (p & -p & x)
                x ^= p;
        if (x) {
            for (auto& p : a)
                if (x & -x & p)
                    p ^= x;
            a.push_back(x);
        }
    }
}

void update(int v) {
    bs[v] = bs[2 * v + 1];
    add(bs[v], bs[2 * v + 2]);
}

void build(int v, int l, int r) {
    bs[v].clear();
    bs[v].reserve(maxc);
    if (r - l > 1) {
        int m = (l + r) / 2;
        build(2 * v + 1, l, m);
        build(2 * v + 2, m, r);
        update(v);
    } else {
        uint val = l ? (a[l] ^ a[l - 1]) : a[l];
        add(bs[v], {val});
        bit_modify(l, val);
    }
}

void modify(int v, int l, int r, int pos, uint what) {
    if (r - l == 1) {
        uint val = (bs[v].empty() ? 0 : bs[v][0]) ^ what;
        bs[v].clear();
        add(bs[v], {val});
        bit_modify(l, what);
    } else {
        int m = (l + r) / 2;
        if (pos < m) {
            modify(2 * v + 1, l, m, pos, what);
        } else {
            modify(2 * v + 2, m, r, pos, what);
        }
        update(v);
    }
}

item result;
void basis(int v, int l, int r, int from, int to) {
    if (r <= from || to <= l)
        return;
    if (from <= l && r <= to) {
        add(result, bs[v]);
        return;
    }
    int m = (l + r) / 2;
    basis(2 * v + 1, l, m, from, to);
    basis(2 * v + 2, m, r, from, to);
}

int main() {
    int n, q;
    scanf("%d%d", &n, &q);
    for (int i = 0; i < n; ++i)
        scanf("%d", a + i);
    build(0, 0, n);
    result.reserve(maxc);
    for (int it = 0; it < q; ++it) {
        int type, l, r;
        scanf("%d%d%d", &type, &l, &r);
        --l;
        if (type == 1) {
            int k;
            scanf("%d", &k);
            modify(0, 0, n, l, k);
            modify(0, 0, n, r, k);
        } else {
            result.clear();
            if (l + 1 < r)
                basis(0, 0, n, l + 1, r);
            add(result, {get_a(l)});
            cout << (1LL << result.size()) << '\n';
        }
    }
}


#include <bits/stdc++.h>
using namespace std;
typedef unsigned int uint;
typedef vector<uint> item;
int const N = 200800;
int const maxc = 33;

item bs[4 * N];
int a[N];
uint bit[N];

void bit_modify(int i, uint what) {
    for (++i; i < N; i += i & -i) {
        bit[i] ^= what;
    }
}

uint get_a(int i) {
    uint res = 0;
    for (++i; i > 0; i &= i - 1) {
        res ^= bit[i];
    }
    return res;
}

void add(item& a, item const& b) {
    for (auto x : b) {
        for (auto p : a)
            if (p & -p & x)
                x ^= p;
        if (x)
            a.push_back(x);
    }
}

void update(int v) {
    bs[v] = bs[2 * v + 1];
    add(bs[v], bs[2 * v + 2]);
}

void build(int v, int l, int r) {
    bs[v].clear();
    bs[v].reserve(maxc);
    if (r - l > 1) {
        int m = (l + r) / 2;
        build(2 * v + 1, l, m);
        build(2 * v + 2, m, r);
        update(v);
    } else {
        uint val = l ? (a[l] ^ a[l - 1]) : a[l];
        add(bs[v], {val});
        bit_modify(l, val);
    }
}

void modify(int v, int l, int r, int pos, uint what) {
    if (r - l == 1) {
        uint val = (bs[v].empty() ? 0 : bs[v][0]) ^ what;
        bs[v].clear();
        add(bs[v], {val});
        bit_modify(l, what);
    } else {
        int m = (l + r) / 2;
        if (pos < m) {
            modify(2 * v + 1, l, m, pos, what);
        } else {
            modify(2 * v + 2, m, r, pos, what);
        }
        update(v);
    }
}

item result;
void basis(int v, int l, int r, int from, int to) {
    if (r <= from || to <= l)
        return;
    if (from <= l && r <= to) {
        add(result, bs[v]);
        return;
    }
    int m = (l + r) / 2;
    basis(2 * v + 1, l, m, from, to);
    basis(2 * v + 2, m, r, from, to);
}

int main() {
    int n, q;
    scanf("%d%d", &n, &q);
    for (int i = 0; i < n; ++i)
        scanf("%d", a + i);
    build(0, 0, n);
    result.reserve(maxc);
    for (int it = 0; it < q; ++it) {
        int type, l, r;
        scanf("%d%d%d", &type, &l, &r);
        --l;
        if (type == 1) {
            int k;
            scanf("%d", &k);
            modify(0, 0, n, l, k);
            if (r < n)
                modify(0, 0, n, r, k);
        } else {
            result.clear();
            if (l + 1 < r)
                basis(0, 0, n, l + 1, r);
            add(result, {get_a(l)});
            cout << (1LL << result.size()) << '\n';
        }
    }
}


#include <stdio.h>
const int N=200050;
const int M=2*N;
struct Gauss
{
	int a[32];
	Gauss(){ for(int i=0;i<32;i++) a[i]=0;}
	void Add(int x)
	{
		for(int i=31;~i;i--)
		{
			if((x>>i)&1)
			{
				if(a[i]) x^=a[i];
				else{ a[i]=x;return;}
			}
			if(x==0) return;
		}
	}
	void Init(){ for(int i=0;i<32;i++) a[i]=0;}
	int Count(){ int ret=0;for(int i=0;i<32;i++) if(a[i]) ret++;return 1<<ret;}
} x[M];
int ls[M],rs[M],a[N],tsz,root;
void upd(int c)
{
	int i;
	for(i=0;i<32;i++) x[c].a[i]=x[ls[c]].a[i];
	for(i=0;i<32;i++) x[c].Add(x[rs[c]].a[i]);
}
void Build(int &c, int ss, int se)
{
	c=++tsz;
	if(ss==se)
	{
		x[c].Add(a[ss]);
		return;
	}
	int mid=ss+se>>1;
	Build(ls[c],ss,mid);
	Build(rs[c],mid+1,se);
	upd(c);
}
void Set(int c, int ss, int se, int qi, int val)
{
	if(qi>se) return;
	if(ss==se)
	{
		x[c].Init();
		x[c].Add(val);
		return;
	}
	int mid=ss+se>>1;
	if(qi<=mid) Set(ls[c],ss,mid,qi,val);
	else Set(rs[c],mid+1,se,qi,val);
	upd(c);
}
Gauss Get(int c, int ss, int se, int qs, int qe)
{
	if(qs>se || ss>qe || qs>qe) return Gauss();
	if(qs<=ss && qe>=se) return x[c];
	int mid=ss+se>>1;
	Gauss ret=Get(ls[c],ss,mid,qs,qe);
	Gauss tmp=Get(rs[c],mid+1,se,qs,qe);
	for(int i=0;i<32;i++) ret.Add(tmp.a[i]);
	return ret;
}
int BIT[N];
void Set(int i, int f){ for(;i<N;i+=i&-i) BIT[i]^=f;}
int Get(int i){ int ret=0;for(;i;i-=i&-i) ret^=BIT[i];return ret;}
int main()
{
	int n,q,i,l,r,t,x;
	scanf("%i %i",&n,&q);
	for(i=1;i<=n;i++) scanf("%i",&a[i]);
	for(i=n;i>=0;i--) a[i]^=a[i-1],Set(i,a[i]);
	Build(root,1,n);
	while(q--)
	{
		scanf("%i %i %i",&t,&l,&r);
		if(t==1)
		{
			scanf("%i",&x);r++;
			a[l]^=x;Set(root,1,n,l,a[l]);Set(l,x);
			a[r]^=x;Set(root,1,n,r,a[r]);Set(r,x);
		}
		else
		{
			Gauss sol=Get(root,1,n,l+1,r);
			sol.Add(Get(l));
			printf("%i\n",sol.Count());
		}
	}
	return 0;
}


#include <stdio.h>
const int N=200050;
const int M=2*N;
struct Gauss
{
	int a[32];
	Gauss(){}
	void Add(int x)
	{
		for(int i=31;~i;i--)
		{
			if((x>>i)&1)
			{
				if(a[i]) x^=a[i];
				else{ a[i]=x;return;}
			}
			if(x==0) return;
		}
	}
	void Init(){ for(int i=0;i<32;i++) a[i]=0;}
	int Count(){ int ret=0;for(int i=0;i<32;i++) if(a[i]) ret++;return 1<<ret;}
} x[M];
int ls[M],rs[M],a[N],tsz,root;
void upd(int c)
{
	int i;
	for(i=0;i<32;i++) x[c].a[i]=x[ls[c]].a[i];
	for(i=0;i<32;i++) x[c].Add(x[rs[c]].a[i]);
}
void Build(int &c, int ss, int se)
{
	c=++tsz;
	if(ss==se)
	{
		x[c].Add(a[ss]);
		return;
	}
	int mid=ss+se>>1;
	Build(ls[c],ss,mid);
	Build(rs[c],mid+1,se);
	upd(c);
}
void Set(int c, int ss, int se, int qi, int val)
{
	if(qi>se) return;
	if(ss==se)
	{
		x[c].Init();
		x[c].Add(val);
		return;
	}
	int mid=ss+se>>1;
	if(qi<=mid) Set(ls[c],ss,mid,qi,val);
	else Set(rs[c],mid+1,se,qi,val);
	upd(c);
}
Gauss Get(int c, int ss, int se, int qs, int qe)
{
	if(qs>se || ss>qe) return Gauss();
	if(qs<=ss && qe>=se) return x[c];
	int mid=ss+se>>1;
	Gauss ret=Get(ls[c],ss,mid,qs,qe);
	Gauss tmp=Get(rs[c],mid+1,se,qs,qe);
	for(int i=0;i<32;i++) ret.Add(tmp.a[i]);
	return ret;
}
int main()
{
	int n,q,i,l,r,t,x;
	scanf("%i %i",&n,&q);
	for(i=1;i<=n;i++) scanf("%i",&a[i]);
	Build(root,1,n);
	while(q--)
	{
		scanf("%i %i %i",&t,&l,&r);
		if(t==1)
		{
			scanf("%i",&x);r++;
			a[l]^=x;Set(root,1,n,l,a[l]);
			a[r]^=x;Set(root,1,n,r,a[r]);
		}
		else printf("%i\n",Get(root,1,n,l,r).Count());
	}
	return 0;
}


#include <stdio.h>
const int N=200050;
const int M=2*N;
struct Gauss
{
	int a[32];
	Gauss(){ for(int i=0;i<32;i++) a[i]=0;}
	void Add(int x)
	{
		for(int i=31;~i;i--)
		{
			if((x>>i)&1)
			{
				if(a[i]) x^=a[i];
				else{ a[i]=x;return;}
			}
			if(x==0) return;
		}
	}
	void Init(){ for(int i=0;i<32;i++) a[i]=0;}
	int Count(){ int ret=0;for(int i=0;i<32;i++) if(a[i]) ret++;return 1<<ret;}
} x[M];
int ls[M],rs[M],a[N],tsz,root;
void upd(int c)
{
	int i;
	for(i=0;i<32;i++) x[c].a[i]=x[ls[c]].a[i];
	for(i=0;i<32;i++) x[c].Add(x[rs[c]].a[i]);
}
void Build(int &c, int ss, int se)
{
	c=++tsz;
	if(ss==se)
	{
		x[c].Add(a[ss]);
		return;
	}
	int mid=ss+se>>1;
	Build(ls[c],ss,mid);
	Build(rs[c],mid+1,se);
	upd(c);
}
void Set(int c, int ss, int se, int qi, int val)
{
	if(qi>se) return;
	if(ss==se)
	{
		x[c].Init();
		x[c].Add(val);
		return;
	}
	int mid=ss+se>>1;
	if(qi<=mid) Set(ls[c],ss,mid,qi,val);
	else Set(rs[c],mid+1,se,qi,val);
	upd(c);
}
Gauss Get(int c, int ss, int se, int qs, int qe)
{
	if(qs>se || ss>qe) return Gauss();
	if(qs<=ss && qe>=se) return x[c];
	int mid=ss+se>>1;
	Gauss ret=Get(ls[c],ss,mid,qs,qe);
	Gauss tmp=Get(rs[c],mid+1,se,qs,qe);
	for(int i=0;i<32;i++) ret.Add(tmp.a[i]);
	return ret;
}
int main()
{
	int n,q,i,l,r,t,x;
	scanf("%i %i",&n,&q);
	for(i=1;i<=n;i++) scanf("%i",&a[i]);
	Build(root,1,n);
	while(q--)
	{
		scanf("%i %i %i",&t,&l,&r);
		if(t==1)
		{
			scanf("%i",&x);r++;
			a[l]^=x;Set(root,1,n,l,a[l]);
			a[r]^=x;Set(root,1,n,r,a[r]);
		}
		else printf("%i\n",Get(root,1,n,l,r).Count());
	}
	return 0;
}


#include <stdio.h>
const int N=200050;
const int M=2*N;
struct Gauss
{
	int a[32];
	Gauss(){ for(int i=0;i<32;i++) a[i]=0;}
	void Add(int x)
	{
		for(int i=31;~i;i--)
		{
			if((x>>i)&1)
			{
				if(a[i]) x^=a[i];
				else{ a[i]=x;return;}
			}
			if(x==0) return;
		}
	}
	void Init(){ for(int i=0;i<32;i++) a[i]=0;}
	int Count(){ int ret=0;for(int i=0;i<32;i++) if(a[i]) ret++;return 1<<ret;}
} x[M];
int ls[M],rs[M],a[N],tsz,root;
void upd(int c)
{
	int i;
	for(i=0;i<32;i++) x[c].a[i]=x[ls[c]].a[i];
	for(i=0;i<32;i++) x[c].Add(x[rs[c]].a[i]);
}
void Build(int &c, int ss, int se)
{
	c=++tsz;
	if(ss==se)
	{
		x[c].Add(a[ss]);
		return;
	}
	int mid=ss+se>>1;
	Build(ls[c],ss,mid);
	Build(rs[c],mid+1,se);
	upd(c);
}
void Set(int c, int ss, int se, int qi, int val)
{
	if(qi>se) return;
	if(ss==se)
	{
		x[c].Init();
		x[c].Add(val);
		return;
	}
	int mid=ss+se>>1;
	if(qi<=mid) Set(ls[c],ss,mid,qi,val);
	else Set(rs[c],mid+1,se,qi,val);
	upd(c);
}
Gauss Get(int c, int ss, int se, int qs, int qe)
{
	if(qs>se || ss>qe || qs>qe) return Gauss();
	if(qs<=ss && qe>=se) return x[c];
	int mid=ss+se>>1;
	Gauss ret=Get(ls[c],ss,mid,qs,qe);
	Gauss tmp=Get(rs[c],mid+1,se,qs,qe);
	for(int i=0;i<32;i++) ret.Add(tmp.a[i]);
	return ret;
}
int BIT[N];
void Set(int i, int f){ for(;i<N;i+=i&-i) BIT[i]^=f;}
int Get(int i){ int ret=0;for(;i;i-=i&-i) ret^=BIT[i];return ret;}
int main()
{
	int n,q,i,l,r,t,x;
	scanf("%i %i",&n,&q);
	for(i=1;i<=n;i++) scanf("%i",&a[i]);
	Build(root,1,n);
	while(q--)
	{
		scanf("%i %i %i",&t,&l,&r);
		if(t==1)
		{
			scanf("%i",&x);r++;
			Set(root,1,n,l,a[l]^x^Get(l));Set(l,x);a[l]^=x;
			Set(root,1,n,r,a[r]^x^Get(r));Set(r,x);a[r]^=x;
		}
		else
		{
			Gauss sol=Get(root,1,n,l+1,r);
			sol.Add(a[l]^Get(l));
			printf("%i\n",sol.Count());
		}
	}
	return 0;
}


#include <stdio.h>
const int N=200050;
const int M=2*N;
struct Gauss
{
	int a[32];
	Gauss(){ for(int i=0;i<32;i++) a[i]=0;}
	void Add(int x)
	{
		for(int i=31;~i;i--)
		{
			if((x>>i)&1)
			{
				if(a[i]) x^=a[i];
				else{ a[i]=x;return;}
			}
			if(x==0) return;
		}
	}
	void Init(){ for(int i=0;i<32;i++) a[i]=0;}
	int Count(){ int ret=0;for(int i=0;i<32;i++) if(a[i]) ret++;return 1<<ret;}
} x[M];
int ls[M],rs[M],a[N],tsz,root;
void upd(int c)
{
	int i;
	for(i=0;i<32;i++) x[c].a[i]=x[ls[c]].a[i];
	for(i=0;i<32;i++) x[c].Add(x[rs[c]].a[i]);
}
void Build(int &c, int ss, int se)
{
	c=++tsz;
	if(ss==se)
	{
		x[c].Add(a[ss]);
		return;
	}
	int mid=ss+se>>1;
	Build(ls[c],ss,mid);
	Build(rs[c],mid+1,se);
	upd(c);
}
void Set(int c, int ss, int se, int qi, int val)
{
	if(qi>se) return;
	if(ss==se)
	{
		x[c].Init();
		x[c].Add(val);
		return;
	}
	int mid=ss+se>>1;
	if(qi<=mid) Set(ls[c],ss,mid,qi,val);
	else Set(rs[c],mid+1,se,qi,val);
	upd(c);
}
Gauss Get(int c, int ss, int se, int qs, int qe)
{
	if(qs>se || ss>qe || qs>qe) return Gauss();
	if(qs<=ss && qe>=se) return x[c];
	int mid=ss+se>>1;
	Gauss ret=Get(ls[c],ss,mid,qs,qe);
	Gauss tmp=Get(rs[c],mid+1,se,qs,qe);
	for(int i=0;i<32;i++) ret.Add(tmp.a[i]);
	return ret;
}
int BIT[N];
void Set(int i, int f){ for(;i<N;i+=i&-i) BIT[i]^=f;}
int Get(int i){ int ret=0;for(;i;i-=i&-i) ret^=BIT[i];return ret;}
int main()
{
	int n,q,i,l,r,t,x;
	scanf("%i %i",&n,&q);
	for(i=1;i<=n;i++) scanf("%i",&a[i]),a[i]^=a[i-1],Set(i,a[i]);
	Build(root,1,n);
	while(q--)
	{
		scanf("%i %i %i",&t,&l,&r);
		if(t==1)
		{
			scanf("%i",&x);r++;
			a[l]^=x;Set(root,1,n,l,a[l]);Set(l,x);
			a[r]^=x;Set(root,1,n,r,a[r]);Set(r,x);
		}
		else
		{
			Gauss sol=Get(root,1,n,l+1,r);
			sol.Add(Get(l));
			printf("%i\n",sol.Count());
		}
	}
	return 0;
}


#include <stdio.h>
const int N=200050;
const int M=2*N;
struct Gauss
{
	int a[32];
	Gauss(){ for(int i=0;i<32;i++) a[i]=0;}
	void Add(int x)
	{
		for(int i=31;~i;i--)
		{
			if((x>>i)&1)
			{
				if(a[i]) x^=a[i];
				else{ a[i]=x;return;}
			}
			if(x==0) return;
		}
	}
	void Init(){ for(int i=0;i<32;i++) a[i]=0;}
	int Count(){ int ret=0;for(int i=0;i<32;i++) if(a[i]) ret++;return 1<<ret;}
} x[M];
int ls[M],rs[M],a[N],tsz,root;
void upd(int c)
{
	int i;
	for(i=0;i<32;i++) x[c].a[i]=x[ls[c]].a[i];
	for(i=0;i<32;i++) x[c].Add(x[rs[c]].a[i]);
}
void Build(int &c, int ss, int se)
{
	c=++tsz;
	if(ss==se)
	{
		x[c].Add(a[ss]);
		return;
	}
	int mid=ss+se>>1;
	Build(ls[c],ss,mid);
	Build(rs[c],mid+1,se);
	upd(c);
}
void Set(int c, int ss, int se, int qi, int val)
{
	if(qi>se) return;
	if(ss==se)
	{
		x[c].Init();
		x[c].Add(val);
		return;
	}
	int mid=ss+se>>1;
	if(qi<=mid) Set(ls[c],ss,mid,qi,val);
	else Set(rs[c],mid+1,se,qi,val);
	upd(c);
}
Gauss Get(int c, int ss, int se, int qs, int qe)
{
	if(qs>se || ss>qe || qs>qe) return Gauss();
	if(qs<=ss && qe>=se) return x[c];
	int mid=ss+se>>1;
	Gauss ret=Get(ls[c],ss,mid,qs,qe);
	Gauss tmp=Get(rs[c],mid+1,se,qs,qe);
	for(int i=0;i<32;i++) ret.Add(tmp.a[i]);
	return ret;
}
int BIT[N];
void Set(int i, int f){ for(;i<N;i+=i&-i) BIT[i]^=f;}
int Get(int i){ int ret=0;for(;i;i-=i&-i) ret^=BIT[i];return ret;}
int main()
{
	int n,q,i,l,r,t,x;
	scanf("%i %i",&n,&q);
	for(i=1;i<=n;i++) scanf("%i",&a[i]);
	Build(root,1,n);
	while(q--)
	{
		scanf("%i %i %i",&t,&l,&r);
		if(t==1)
		{
			scanf("%i",&x);r++;
			Set(root,1,n,l,a[l]^x^Get(l));Set(l,x);
			Set(root,1,n,r,a[r]^x^Get(r));Set(r,x);
		}
		else
		{
			Gauss sol=Get(root,1,n,l+1,r);
			sol.Add(a[l]^Get(l));
			printf("%i\n",sol.Count());
		}
	}
	return 0;
}


#include <stdio.h>
const int N=200050;
const int M=2*N;
struct Gauss
{
	int a[32];
	Gauss(){ for(int i=0;i<32;i++) a[i]=0;}
	void Add(int x)
	{
		for(int i=31;~i;i--)
		{
			if((x>>i)&1)
			{
				if(a[i]) x^=a[i];
				else{ a[i]=x;return;}
			}
			if(x==0) return;
		}
	}
	void Init(){ for(int i=0;i<32;i++) a[i]=0;}
	int Count(){ int ret=0;for(int i=0;i<32;i++) if(a[i]) ret++;return 1<<ret;}
} x[M];
int ls[M],rs[M],a[N],tsz,root;
void upd(int c)
{
	int i;
	for(i=0;i<32;i++) x[c].a[i]=x[ls[c]].a[i];
	for(i=0;i<32;i++) x[c].Add(x[rs[c]].a[i]);
}
void Build(int &c, int ss, int se)
{
	c=++tsz;
	if(ss==se)
	{
		x[c].Add(a[ss]);
		return;
	}
	int mid=ss+se>>1;
	Build(ls[c],ss,mid);
	Build(rs[c],mid+1,se);
	upd(c);
}
void Set(int c, int ss, int se, int qi, int val)
{
	if(qi>se) return;
	if(ss==se)
	{
		x[c].Init();
		x[c].Add(val);
		return;
	}
	int mid=ss+se>>1;
	if(qi<=mid) Set(ls[c],ss,mid,qi,val);
	else Set(rs[c],mid+1,se,qi,val);
	upd(c);
}
Gauss Get(int c, int ss, int se, int qs, int qe)
{
	if(qs>se || ss>qe || qs>qe) return Gauss();
	if(qs<=ss && qe>=se) return x[c];
	int mid=ss+se>>1;
	Gauss ret=Get(ls[c],ss,mid,qs,qe);
	Gauss tmp=Get(rs[c],mid+1,se,qs,qe);
	for(int i=0;i<32;i++) ret.Add(tmp.a[i]);
	return ret;
}
int BIT[N];
void Set(int i, int f){ for(;i<N;i+=i&-i) BIT[i]^=f;}
int Get(int i){ int ret=0;for(;i;i-=i&-i) ret^=BIT[i];return ret;}
int main()
{
	int n,q,i,l,r,t,x;
	scanf("%i %i",&n,&q);
	for(i=1;i<=n;i++) scanf("%i",&a[i]);
	for(i=n;i>=1;i--) a[i]^=a[i-1],Set(i,a[i]);
	Build(root,1,n);
	while(q--)
	{
		scanf("%i %i %i",&t,&l,&r);
		if(t==1)
		{
			scanf("%i",&x);r++;
			a[l]^=x;Set(root,1,n,l,a[l]);Set(l,x);
			a[r]^=x;Set(root,1,n,r,a[r]);Set(r,x);
		}
		else
		{
			Gauss sol=Get(root,1,n,l+1,r);
			sol.Add(Get(l));
			printf("%i\n",sol.Count());
		}
	}
	return 0;
}


#include <bits/stdc++.h>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
const int mx = 2e5 + 10;
int n,m,a[mx],b[mx];
int pre[mx],mv;
struct node{
	int gao[31];
	void add(int x){
		for(int i=29;i>=0;i--){
			if(x&(1<<i)){
				if(!gao[i]){
					gao[i] = x;
					break;
				}else x ^= gao[i];
			}
		}
	}
	node operator + (node A)const
	{
		node ret = A;
		for(int i=29;i>=0;i--)
		if(gao[i]) ret.add(gao[i]);
		return ret;
	}
}s[mx<<2];
void add(int x,int v){
	while(x<=n){
		pre[x] ^= v;
		x += x&(-x);
	}
}
int getpre(int x){
	int ans = 0;
	while(x){
		ans ^= pre[x];
		x -= x&(-x);
	}
	return ans;
}
void build(int l,int r,int rt)
{
	if(l==r){
		b[l] = a[l]^a[l+1];
		for(int i=29;i>=0;i--)
		if((1<<i)&b[l]){
			s[rt].gao[i] = b[l];
			break;
		}
		return ;
	}
	int mid = (l+r)>>1;
	build(lson);build(rson);
	s[rt] = s[rt<<1] + s[rt<<1|1];
}
void update(int l,int r,int rt,int M)
{
	if(l==r){
		b[l] ^= mv;
		memset(s[rt].gao,0,sizeof(s[rt].gao));
		for(int i=29;i>=0;i--)
		if((1<<i)&b[l]){
			s[rt].gao[i] = b[l];
			break;
		}
		return ;
	}
	int mid = (l+r)>>1;
	if(M<=mid) update(lson,M);
	else update(rson,M);
	s[rt] = s[rt<<1] + s[rt<<1|1];
}
node query(int l,int r,int rt,int L,int R)
{
	if(L<=l&&r<=R) return s[rt];
	int mid = (l+r)>>1;
	if(L<=mid&&R>mid) return query(lson,L,R) + query(rson,L,R);
	if(L<=mid) return query(lson,L,R);
	return query(rson,L,R);
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",a+i);
	if(n>1) build(1,n-1,1);
	int o,l,r;
	while(m--){
		scanf("%d%d%d",&o,&l,&r);
		if(o==1){
			scanf("%d",&mv);
			add(l,mv);add(r+1,mv);
			if(l>1) update(1,n-1,1,l-1);
			if(r<n) update(1,n-1,1,r);
		}else{
			int v = a[l]^getpre(l);
			if(n==1||l==r) printf("%d\n",v?2:1);
			else{
				node ans = query(1,n-1,1,l,r-1);
				ans.add(v);
				int ret = 0;
				for(int i=29;i>=0;i--)
				if(ans.gao[i]) ret++;
				printf("%d\n",1<<ret);
			}
		}
	}
    return 0;
}


#include <bits/stdc++.h>

using namespace std;
const int maxn = 1e5;
struct node {
    int bas[30],lazy,st;
    void init() {
        memset(bas,0,sizeof(bas));
        lazy = 0;st = 0;
    }
    int Count() {
        int ans = 0;
        for(int i = 0;i<=29;i++) {
            if(bas[i]) ans++;
        }
        return ans;
    }
    void add(int x) {
        for(int i = 29;i>=0;i--) {
            if((x>>i)&1){
                if(bas[i])x^=bas[i];
                else {
                    bas[i] = x;
                    break;
                }
            }
        }
    }
    node operator + (const node &a) const{
        node ans;  ans.init();
        for(int i = 0;i<=29;i++) {
            ans.add(bas[i]);
            ans.add(a.bas[i]);
        }
        ans.add(st^a.st);
        ans.st = a.st;
        return ans;
    }
}tr[8*maxn],ans;
int n,q;
void pushdown(int st) {
    if(tr[st].lazy) {
        tr[st<<1].lazy ^= tr[st].lazy;
        tr[st<<1].st ^= tr[st].lazy;
        tr[st<<1|1].lazy ^= tr[st].lazy;
        tr[st<<1|1].st ^= tr[st].lazy;
        tr[st].lazy = 0;
    }
}
void build(int l,int r,int st) {
    tr[st].init();
    if(l == r) {
        scanf("%d",&tr[st].st);
        return ;
    }
    int mid = (l+r)>>1;
    build(l,mid,st<<1);
    build(mid+1,r,st<<1|1);
    tr[st] = tr[st<<1] + tr[st<<1|1];
}
void update(int l,int r,int st,int L,int R,int d) {
    if(l>=L && r<=R) {
        tr[st].lazy ^= d;
        tr[st].st ^= d;
        return ;
    }
    pushdown(st);
    int mid = (l+r) >>1;
    if(L<=mid) update(l,mid,st<<1,L,R,d);
    if(R> mid) update(mid+1,r,st<<1|1,L,R,d);
    tr[st] = tr[st<<1] + tr[st<<1|1];
}
void Query(int l,int r,int st,int L,int R) {
    if(l >= L && r <= R) {
        ans = ans + tr[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);
    tr[st] = tr[st<<1] + tr[st<<1|1];
}
int main() {
    int op,l,r,d;
    scanf("%d %d",&n,&q);
    build(1,n,1);
    while(q--) {
        scanf("%d %d %d",&op,&l,&r);
        if(op == 1) {
            scanf("%d",&d);
            update(1,n,1,l,r,d);
        }
        else {
            ans.init();
            Query(1,n,1,l,r);
            printf("%d\n",1<<ans.Count());
        }
    }
    return 0;
}


//let's do it
 #include <iostream>
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
#define inf 1000000000000
#define mod 1000000007
#define pb push_back
#define mp make_pair
#define all(v) v.begin(),v.end()
#define S second
#define F first
#define boost1 ios::sync_with_stdio(false);
#define boost2 cin.tie(0);
#define mem(a,val) memset(a,val,sizeof a)
#define endl "\n"
#define maxn 200005

int tree1[4*maxn],arr[maxn],brr[maxn],lazy1[4*maxn],power[31];
vector<int>ranges;

struct gauss
{
    int basis[31];
    void reset()
    {
        mem(basis,0);
    }
    void add(int num)
    {
        for(int i=30;i>=0;i--)
        {
            if(num&(1<<i))
            {
                if(basis[i])
                num=num^basis[i];
                else
                {
                    basis[i]=num;
                    return;
                }
            }
        }
        return;
    }
};
struct st
{
	int value;
	struct gauss gaussian;
}tree2[4*maxn];

void build1(int node,int a,int b)
{
	if(a==b)
	{
		tree1[node]=arr[a];
		return;
	}
	int mid=(a+b)/2;
	build1(2*node,a,mid);
	build1(2*node+1,mid+1,b);
	tree1[node]=tree1[2*node]^tree1[2*node+1];
}
void update1(int node,int a,int b,int l,int r,int val)
{
	if(lazy1[node]!=0)
	{
		if((b-a+1)%2)
		tree1[node]^=lazy1[node];
		if(a!=b)
		{
			lazy1[2*node]^=lazy1[node];
			lazy1[2*node+1]^=lazy1[node];
		}
		lazy1[node]=0;
	}
	if(a>b || a>r || b<l)
	return;
	if(a>=l && b<=r)
	{
		if((b-a+1)%2)
		tree1[node]^=val;
		if(a!=b)
		{
			lazy1[2*node]^=val;
			lazy1[2*node+1]^=val;
		}
		return;
	}
	int mid=(a+b)/2;
	update1(2*node,a,mid,l,r,val);
	update1(2*node+1,mid+1,b,l,r,val);
	tree1[node]=tree1[2*node]^tree1[2*node+1];
}
int query1(int node,int a,int b,int ind)
{
	if(lazy1[node]!=0)
	{
		if((b-a+1)%2)
		tree1[node]^=lazy1[node];
		if(a!=b)
		{
			lazy1[2*node]^=lazy1[node];
			lazy1[2*node+1]^=lazy1[node];
		}
		lazy1[node]=0;
	}
	if(a>b || a>ind || b<ind)
	return 0;
	if(a==b)
	return tree1[node];
	int mid=(a+b)/2;
	if(ind<=mid)
	return query1(2*node,a,mid,ind);
	else
	return query1(2*node+1,mid+1,b,ind);
}
void build2(int node,int a,int b)
{
	if(a==b)
	{
		tree2[node].gaussian.add(brr[a]);
		tree2[node].value=brr[a];
		return;
	}
	int mid=(a+b)/2;
	build2(2*node,a,mid);
	build2(2*node+1,mid+1,b);
	tree2[node].value=tree2[2*node].value^tree2[2*node+1].value;
	for(int i=0;i<=30;i++)
	tree2[node].gaussian.basis[i]=tree2[2*node].gaussian.basis[i];
	for(int i=0;i<=30;i++)
	{
		if(tree2[2*node+1].gaussian.basis[i])
		tree2[node].gaussian.add(tree2[2*node+1].gaussian.basis[i]);
	}
}
void update2(int node,int a,int b,int ind,int val)
{
	if(a>b || a>ind || b<ind)
	return;
	if(a==b)
	{
		tree2[node].gaussian.reset();
		tree2[node].gaussian.add(val);
		tree2[node].value=val;
		return;
	}
	int mid=(a+b)/2;
	if(ind<=mid)
	update2(2*node,a,mid,ind,val);
	else
	update2(2*node+1,mid+1,b,ind,val);
	tree2[node].value=tree2[2*node].value^tree2[2*node+1].value;
	for(int i=0;i<=30;i++)
	tree2[node].gaussian.basis[i]=tree2[2*node].gaussian.basis[i];
	for(int i=0;i<=30;i++)
	{
		if(tree2[2*node+1].gaussian.basis[i])
		tree2[node].gaussian.add(tree2[2*node+1].gaussian.basis[i]);
	}
}
int query2(int node,int a,int b,int ind)
{
	if(a>b || a>ind || b<ind)
	return 0;
	if(a==b)
	return tree2[node].value;
	int mid=(a+b)/2;
	if(ind<=mid)
	return query2(2*node,a,mid,ind);
	else
	return query2(2*node+1,mid+1,b,ind);
}
void query2_(int node,int a,int b,int l,int r)
{
	if(a>b || a>r || b<l)
	return;
	if(a>=l && b<=r)
	{
		ranges.pb(node);
		return;
	}
	int mid=(a+b)/2;
	query2_(2*node,a,mid,l,r);
	query2_(2*node+1,mid+1,b,l,r);
}
int main()
{
	//boost1;boost2;
	int i,j,n,x,y,type,l,r,val,q,sz;
	power[0]=1;
	for(i=1;i<=30;i++)
	power[i]=2*power[i-1];
	for(i=0;i<4*maxn;i++)
	tree2[i].gaussian.reset();
	scanf("%d%d",&n,&q);
	for(i=1;i<=n;i++)
	scanf("%d",&arr[i]);
	brr[1]=arr[1];
	for(i=2;i<=n;i++)
	brr[i]=arr[i-1]^arr[i];
	build1(1,1,n);
	build2(1,1,n);
	while(q--)
	{
		scanf("%d",&type);
		if(type==1)
		{
			scanf("%d%d%d",&l,&r,&val);
			update1(1,1,n,l,r,val);
			x=query2(1,1,n,l);
			update2(1,1,n,l,x^val);
			if(r+1<=n)
			{
				x=query2(1,1,n,r+1);
				update2(1,1,n,r+1,x^val);
			}
		}
		else
		{
			scanf("%d%d",&l,&r);
			x=query1(1,1,n,l);
			if(l==r)
			{
				if(x==0)
				printf("1\n");
				else
				printf("2\n");
				continue;
			}
			struct gauss now;
			now.reset();
			now.add(x);
			ranges.clear();
			query2_(1,1,n,l+1,r);
			assert(ranges.size()!=0);
			for(auto it:ranges)
			{
				for(i=0;i<=30;i++)
				{
					if(tree2[it].gaussian.basis[i])
					now.add(tree2[it].gaussian.basis[i]);
				}
			}
			sz=0;
			for(i=0;i<=30;i++)
			{
				if(now.basis[i])
				sz++;
			}
			printf("%d\n",power[sz]);
		}
	}
	return 0;
}
/*
5 3
1 2 3 4 2
2 1 5
1 2 2 8
2 1 5
*/


//let's do it
 #include <iostream>
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
#define inf 1000000000000
#define mod 1000000007
#define pb push_back
#define mp make_pair
#define all(v) v.begin(),v.end()
#define S second
#define F first
#define boost1 ios::sync_with_stdio(false);
#define boost2 cin.tie(0);
#define mem(a,val) memset(a,val,sizeof a)
#define endl "\n"
#define maxn 200005

int tree1[4*maxn],arr[maxn],brr[maxn],lazy1[4*maxn],power[31];
vector<int>ranges;

struct gauss
{
    int basis[31];
    void reset()
    {
        mem(basis,0);
    }
    void add(int num)
    {
        for(int i=30;i>=0;i--)
        {
            if(num&(1<<i))
            {
                if(basis[i])
                num=num^basis[i];
                else
                {
                    basis[i]=num;
                    return;
                }
            }
        }
        return;
    }
};
struct st
{
	int value;
	struct gauss gaussian;
}tree2[4*maxn];

void build1(int node,int a,int b)
{
	if(a==b)
	{
		tree1[node]=arr[a];
		return;
	}
	int mid=(a+b)/2;
	build1(2*node,a,mid);
	build1(2*node+1,mid+1,b);
	tree1[node]=tree1[2*node]^tree1[2*node+1];
}
void update1(int node,int a,int b,int l,int r,int val)
{
	if(lazy1[node]!=0)
	{
		if((b-a+1)%2)
		tree1[node]^=lazy1[node];
		if(a!=b)
		{
			lazy1[2*node]^=lazy1[node];
			lazy1[2*node+1]^=lazy1[node];
		}
		lazy1[node]=0;
	}
	if(a>b || a>r || b<l)
	return;
	if(a>=l && b<=r)
	{
		if((b-a+1)%2)
		tree1[node]^=val;
		if(a!=b)
		{
			lazy1[2*node]^=val;
			lazy1[2*node+1]^=val;
		}
		return;
	}
	int mid=(a+b)/2;
	update1(2*node,a,mid,l,r,val);
	update1(2*node+1,mid+1,b,l,r,val);
	tree1[node]=tree1[2*node]^tree1[2*node+1];
}
int query1(int node,int a,int b,int ind)
{
	if(lazy1[node]!=0)
	{
		if((b-a+1)%2)
		tree1[node]^=lazy1[node];
		if(a!=b)
		{
			lazy1[2*node]^=lazy1[node];
			lazy1[2*node+1]^=lazy1[node];
		}
		lazy1[node]=0;
	}
	if(a>b || a>ind || b<ind)
	return 0;
	if(a==b)
	return tree1[node];
	int mid=(a+b)/2;
	if(ind<=mid)
	return query1(2*node,a,mid,ind);
	else
	return query1(2*node+1,mid+1,b,ind);
}
void build2(int node,int a,int b)
{
	if(a==b)
	{
		tree2[node].gaussian.add(brr[a]);
		tree2[node].value=brr[a];
		return;
	}
	int mid=(a+b)/2;
	build2(2*node,a,mid);
	build2(2*node+1,mid+1,b);
	tree2[node].value=tree2[2*node].value^tree2[2*node+1].value;
	for(int i=0;i<=30;i++)
	tree2[node].gaussian.basis[i]=tree2[2*node].gaussian.basis[i];
	for(int i=0;i<=30;i++)
	{
		if(tree2[2*node+1].gaussian.basis[i])
		tree2[node].gaussian.add(tree2[2*node+1].gaussian.basis[i]);
	}
}
void update2(int node,int a,int b,int ind,int val)
{
	if(a>b || a>ind || b<ind)
	return;
	if(a==b)
	{
		tree2[node].gaussian.reset();
		tree2[node].gaussian.add(val);
		tree2[node].value=val;
		return;
	}
	int mid=(a+b)/2;
	if(ind<=mid)
	update2(2*node,a,mid,ind,val);
	else
	update2(2*node+1,mid+1,b,ind,val);
	tree2[node].value=tree2[2*node].value^tree2[2*node+1].value;
	for(int i=0;i<=30;i++)
	tree2[node].gaussian.basis[i]=tree2[2*node].gaussian.basis[i];
	for(int i=0;i<=30;i++)
	{
		if(tree2[2*node+1].gaussian.basis[i])
		tree2[node].gaussian.add(tree2[2*node+1].gaussian.basis[i]);
	}
}
int query2(int node,int a,int b,int ind)
{
	if(a>b || a>ind || b<ind)
	return 0;
	if(a==b)
	return tree2[node].value;
	int mid=(a+b)/2;
	if(ind<=mid)
	return query2(2*node,a,mid,ind);
	else
	return query2(2*node+1,mid+1,b,ind);
}
void query2_(int node,int a,int b,int l,int r)
{
	if(a>b || a>r || b<l)
	return;
	if(a>=l && b<=r)
	{
		ranges.pb(node);
		return;
	}
	int mid=(a+b)/2;
	query2_(2*node,a,mid,l,r);
	query2_(2*node+1,mid+1,b,l,r);
}
int main()
{
	boost1;boost2;
	int i,j,n,x,y,type,l,r,val,q,sz;
	power[0]=1;
	for(i=1;i<=30;i++)
	power[i]=2*power[i-1];
	for(i=0;i<4*maxn;i++)
	tree2[i].gaussian.reset();
	cin>>n>>q;
	for(i=1;i<=n;i++)
	cin>>arr[i];
	brr[1]=arr[1];
	for(i=2;i<=n;i++)
	brr[i]=arr[i-1]^arr[i];
	build1(1,1,n);
	build2(1,1,n);
	while(q--)
	{
		cin>>type;
		if(type==1)
		{
			cin>>l>>r>>val;
			update1(1,1,n,l,r,val);
			x=query2(1,1,n,l);
			update2(1,1,n,l,x^val);
			if(r+1<=n)
			{
				x=query2(1,1,n,r+1);
				update2(1,1,n,r+1,x^val);
			}
		}
		else
		{
			cin>>l>>r;
			x=query1(1,1,n,l);
			if(l==r)
			{
				if(x==0)
				cout<<"1"<<endl;
				else
				cout<<"2"<<endl;
				continue;
			}
			struct gauss now;
			now.reset();
			now.add(x);
			ranges.clear();
			query2_(1,1,n,l+1,r);
			assert(ranges.size()!=0);
			for(auto it:ranges)
			{
				for(i=0;i<=30;i++)
				{
					if(tree2[it].gaussian.basis[i])
					now.add(tree2[it].gaussian.basis[i]);
				}
			}
			sz=0;
			for(i=0;i<=30;i++)
			{
				if(now.basis[i])
				sz++;
			}
			cout<<power[sz]<<endl;
		}
	}
	return 0;
}
/*
5 3
1 2 3 4 2
2 1 5
1 2 2 8
2 1 5
*/


#include<bits/stdc++.h>

using namespace std;

#define lch     i << 1
#define rch     i << 1 | 1

const int   N   = 2e5 + 1;

typedef vector<int> vi;

int t1[N << 1];
vi  t2[N << 1];

void add(vi &v,int x)   {
    for(int &a : v)
        if (a & -a & x) x ^= a;
    if (x == 0) return;
    for(int &a : v)
        if (x & -x & a) a ^= x;
    v.push_back(x);
}
vi  operator + (vi a,vi b) {
    if (a.size() < b.size())
        a.swap(b);
    for(int x : b)
        add(a,x);
    return  a;
}

int a[N];

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

    int n;  cin >> n;
    int q;  cin >> q;

    auto updValue = [&](int l,int r,int v)  {
        l += n - 1;
        r += n;
        for(; l < r ; l >>= 1, r >>= 1) {
            if (l & 1)  t1[l++] ^= v;
            if (r & 1)  t1[--r] ^= v;
        }
    };
    auto getValue = [&](int p)  {
        int ans = 0;
        for(p += n - 1 ; p ; p >>= 1)
            ans ^= t1[p];
        return  ans;
    };
    auto updGauss = [&](int p,int v)    {
        t2[p += n - 1].clear();
        add(t2[p],v);
        for(; p > 1 ; p >>= 1)
            t2[p >> 1] = t2[p] + t2[p ^ 1];
    };
    auto getGauss = [&](int l,int r)    {
        vi  C;
        add(C,getValue(l));

        l += n;
        r += n;

        for(; l < r ; l >>= 1, r >>= 1) {
            if (l & 1)  C = C + t2[l++];
            if (r & 1)  C = C + t2[--r];
        }

        return  (1 << C.size());
    };

    for(int i = 1 ; i <= n ; ++i)   {
        cin >> a[i];
        updValue(i,i,a[i]);
        updGauss(i,a[i] ^ a[i - 1]);
    }
    for(int i = n ; i >= 1 ; --i)
        a[i] ^= a[i - 1];

    for(int i = 1 ; i <= q ; ++i)   {
        int t;  cin >> t;
        int l;  cin >> l;
        int r;  cin >> r;

        if (t == 1) {
            int k;  cin >> k;
            updValue(l,r,k);    ++r;
            updGauss(l,a[l] ^= k);
            updGauss(r,a[r] ^= k);

            continue;
        }
        if (t == 2)
            cout << getGauss(l,r) << "\n";
    }
}


#include<bits/stdc++.h>

using namespace std;

#define lch     i << 1
#define rch     i << 1 | 1

const int   N   = 2e5 + 1;

typedef vector<int> vi;

int t1[N << 1];
vi  t2[N << 1];

void add(vi &v,int x)   {
    for(int &a : v)
        if (a & -a & x) x ^= a;
    if (x == 0) return;
    for(int &a : v)
        if (x & -x & a) a ^= x;
    v.push_back(x);
}
vi  operator + (vi a,vi b) {
    if (a.size() < b.size())
        a.swap(b);
    for(int x : b)
        add(a,x);
    return  a;
}

int a[N];

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

    int n;  cin >> n;
    int q;  cin >> q;

    auto upd = [&](int p,int v) {
        t2[p += n - 1] = {v};
        for(; p > 1 ; p >>= 1)
            t2[p >> 1] = t2[p] + t2[p ^ 1];
    };
    auto get = [&](int l,int r) {
        vi  C;
        add(C,a[l] ^ a[l - 1]);

        l += n;
        r += n;

        for(; l < r ; l >>= 1, r >>= 1) {
            if (l & 1)  C = C + t2[l++];
            if (r & 1)  C = C + t2[--r];
        }

        return  (1 << C.size());
    };

    for(int i = 1 ; i <= n ; ++i)   {
        cin >> a[i];
        upd(i, a[i] ^ a[i - 1]);
    }
    for(int i = n ; i >= 1 ; --i)
        a[i] ^= a[i - 1];

    for(int i = 1 ; i <= q ; ++i)   {
        int t;  cin >> t;
        int l;  cin >> l;
        int r;  cin >> r;

        if (t == 1) {
            int k;  cin >> k;
            upd(l,a[l] ^= k);   ++r;
            upd(r,a[r] ^= k);

            continue;
        }
        if (t == 2)
            cout << get(l,r) << "\n";
    }
}


#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;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <assert.h>
#include <bitset>
using namespace std;

const int N = 200020;
struct tree {
	int lt, rt;
	int a[30];

	tree() {
		memset(a, 0, sizeof(a));
	}

    void insert(int x) {
	   for (int i = 29; i >= 0; i--) {
		   if ((x >> i) & 1) {
			   if (!a[i]) {
				   a[i] = x;
				   return;
			   }
			   x ^= a[i];
		   }
	   }
	}

}a[N << 2];
int c[N];

void merge(tree &a, tree b, tree c) {
	for (int i = 0; i < 30; i++) a.a[i] = b.a[i];
	for (int i = 0; i < 30; i++)
		if (c.a[i])
			a.insert(c.a[i]);
}

void init(int lt, int rt, int step) {
	a[step].lt = lt;
	a[step].rt = rt;
	if (lt == rt) {
		a[step].insert(c[lt] ^ c[lt + 1]);
		return;
	}

	int mid = (lt + rt) >> 1;
	init(lt, mid, step << 1);
	init(mid + 1, rt, step << 1 | 1);
	merge(a[step], a[step << 1], a[step << 1 | 1]);
}

tree query(int lt, int rt, int step) {
    if (lt == a[step].lt && rt == a[step].rt) return a[step];
	if (rt <= a[step << 1].rt) return query(lt, rt, step << 1);
	if (lt > a[step << 1].rt) return query(lt, rt, step << 1 | 1);
	tree l = query(lt, a[step << 1].rt, step << 1);
	tree r = query(a[step << 1 | 1].lt, rt, step << 1 | 1);
	tree ans;
	merge(ans, l, r);
	return ans;
}

void update(int pos, int step, int x) {
	if (a[step].lt == a[step].rt) {
		memset(a[step].a, 0, sizeof(a[step].a));
		a[step].insert(x);
		return;
	}

	if (pos <= a[step << 1].rt) update(pos, step << 1, x);
	else update(pos, step << 1 | 1, x);
	merge(a[step], a[step << 1], a[step << 1 | 1]);
}

int b[N];

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

void insert(int x, int y) {
	for (int i = x; i < N; i += lowbit(i))
		b[i] ^= y;
}

int query(int x) {
	int ans = 0;
	for (int i = x; i > 0; i -= lowbit(i))
		ans ^= b[i];
	return ans;
}

int main()
{
	int n, m;
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &c[i]);
	}

	init(0, n, 1);

	while (m--) {
		int t, l, r, k;
		scanf("%d%d%d", &t, &l, &r);
		if (t == 2) {
			if (l == r) {
				int x = c[l] ^ query(l);
				if (x) x = 2;
				else x = 1;
				printf("%d\n", x);
				continue;
			}

			tree ans = query(l, r - 1, 1);
		    ans.insert(query(l) ^ c[l]);
			int tot = 0;
			for (int i = 0; i < 30; i++)
				if (ans.a[i]) tot++;
			printf("%d\n", (1 << tot));
		} else {
			scanf("%d", &k);
			insert(l, k);
			insert(r + 1, k);
			update(l - 1, 1, c[l] ^ c[l - 1] ^ query(l) ^ query(l - 1));
			if (r < n) update(r, 1, c[r] ^ c[r + 1] ^ query(r) ^ query(r + 1));
		}
	}

	return 0;
}


#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 query(int l,int r,int id)
	{
		Base res;
		if(l>=ql&&r<=qr) return v[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 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;
		return query(1,n,1);
	}
	#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;
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)
	{
		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();
			v[id].insert(qv^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 query(int l,int r,int id)
	{
		Base res;
		res.init();
		if(l>=ql&&r<=qr) return v[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 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;
		return query(1,n,1);
	}
	#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);
				tr.upd(l,l,x);
				if(r-1>0) tr.upd(r-1,r-1,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;
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)
	{
		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();
			v[id].insert(qv^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 query(int l,int r,int id)
	{
		Base res;
		res.init();
		if(l>=ql&&r<=qr) return v[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 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;
		return query(1,n,1);
	}
	#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];
		tr.build(n-1);
		while(q--)
		{
			read(op,l,r);
			if(op==1)
			{
				read(x);
				tr.upd(l,l,x);
				tr.upd(r-1,r-1,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;
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)
	{
		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();
			v[id].insert(qv^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 query(int l,int r,int id)
	{
		Base res;
		res.init();
		if(l>=ql&&r<=qr) return v[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 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;
		return query(1,n,1);
	}
	#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;
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)
	{
		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();
			v[id].insert(qv^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 query(int l,int r,int id)
	{
		Base res;
		res.init();
		if(l>=ql&&r<=qr) return v[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 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;
		return query(1,n,1);
	}
	#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];
		tr.build(n-1);
		while(q--)
		{
			read(op,l,r);
			if(op==1)
			{
				read(x);
				tr.upd(l,l,x);
				if(r-1>0) tr.upd(r-1,r-1,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;
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)
	{
		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 query(int l,int r,int id)
	{
		Base res;
		if(l>=ql&&r<=qr) return v[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 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;
		return query(1,n,1);
	}
	#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);
			}
		}
	}
}