#include <bits/stdc++.h>

using namespace std;

#define MAXN 1010

long long n,q;
vector<pair<pair<long long,long long>,string> > upiti;
long long parent[MAXN];
long long siz[MAXN];
string seg[MAXN*4];
long long segtree[MAXN*4];

long long get(long long node)
{
    if (parent[node]==node) return node;
    else return get(parent[node]);
}

void unite(long long node1,long long node2)
{
    node1=get(node1),node2=get(node2);
    if (node1!=node2)
    {
        if (siz[node1]<siz[node2]) swap(node1,node2);
        parent[node2]=node1;siz[node1]+=siz[node2];
    }
}

void build(long long node,long long l,long long r)
{
    if (l==r) seg[node]=" ";
    else
    {
        long long mid=(l+r)/2;
        build(2*node,l,mid);
        build(2*node+1,mid+1,r);
        seg[node]=seg[2*node]+seg[2*node+1];
    }
}

void update(long long node,long long l,long long r,long long pos,string val)
{
    if (l==r) seg[node]=val;
    else
    {
        long long mid=(l+r)/2;
        if (pos<=mid) update(2*node,l,mid,pos,val);
        else update(2*node+1,mid+1,r,pos,val);
        seg[node]=seg[2*node]+seg[2*node+1];
    }
}

string query(long long node,long long l,long long r,long long a,long long b)
{
    if (a>b) return "";
    if (l==a and r==b) return seg[node];
    long long mid=(l+r)/2;
    return query(2*node,l,mid,a,min(b,mid))+query(2*node+1,mid+1,r,max(a,mid+1),b);
}

void buildtree(long long node,long long l,long long r)
{
    if (l==r) segtree[node]=0;
    else
    {
        long long mid=(l+r)/2;
        build(2*node,l,mid);
        build(2*node+1,mid+1,r);
        segtree[node]=segtree[2*node]+segtree[2*node+1];
    }
}

void updatetree(long long node,long long l,long long r,long long pos)
{
    if (l==r) segtree[node]=1;
    else
    {
        long long mid=(l+r)/2;
        if (pos<=mid) updatetree(2*node,l,mid,pos);
        else updatetree(2*node+1,mid+1,r,pos);
        segtree[node]=segtree[2*node]+segtree[2*node+1];
    }
}

long long querytree(long long node,long long l,long long r,long long a,long long b)
{
    if (a>b) return 0;
    if (l==a and r==b) return segtree[node];
    long long mid=(l+r)/2;
    return querytree(2*node,l,mid,a,min(b,mid))+querytree(2*node+1,mid+1,r,max(a,mid+1),b);
}

int main()
{
    ios_base::sync_with_stdio(false);
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n>>q;
    for (long long i=1;i<=n;i++) parent[i]=i;
    for (long long i=1;i<=n;i++) siz[i]=1;
    long long bra=0;
    bool da=true;
    for (long long i=1;i<=q;i++)
    {
        long long t;cin>>t;
        if (t==1)
        {
            long long a,b;cin>>a>>b;
            if (a==b+1) swap(a,b);
            string c;cin>>c;
            if (b!=a+1) da=false;
            upiti.push_back({{a,b},c});
            if (c=="a") bra++;
        }
        if (t==2)
        {
            long long a,b;cin>>a>>b;bra++;
            upiti.push_back({{a,b}," "});
        }
    }
    if (bra==q)
    {
        ///1.subtask-proslo
        for (long long i=0;i<q;i++)
        {
            long long a=upiti[i].first.first;
            long long b=upiti[i].first.second;
            string c=upiti[i].second;
            if (c!=" ") {unite(a,b);continue;}
            a=get(a);b=get(b);
            if (a==b) cout<<1<<endl;
            else cout<<0<<endl;
        }
        return 0;
    }
    if (da)
    {
        ///2.subtask-nije proslo nmp zasto voli
        build(1,1,n-1);buildtree(1,1,n-1);
        for (long long i=0;i<q;i++)
        {
            long long a=upiti[i].first.first;
            long long b=upiti[i].first.second;
            string c=upiti[i].second;
            if (c!=" ") {update(1,1,n-1,a,c);updatetree(1,1,n-1,a);continue;}
            long long br=querytree(1,1,n-1,a,b-1);
            if (br!=b-a) {cout<<0<<endl;continue;}
            string s=query(1,1,n-1,a,b-1);
            string t=s;reverse(t.begin(),t.end());
            if (t==s) cout<<1<<endl;
            else cout<<0<<endl;
        }
        return 0;
    }
    return 0;
}