#include <bits/stdc++.h>
using namespace std;
template <typename T>
inline int Chkmax(T &a, T b) {
  return a < b ? a = b, 1 : 0;
}
template <typename T>
inline int Chkmin(T &a, T b) {
  return a > b ? a = b, 1 : 0;
}
template <typename T>
inline T read() {
  T sum = 0, fl = 1;
  char ch = getchar();
  for (; !isdigit(ch); ch = getchar())
    if (ch == '-') fl = -1;
  for (; isdigit(ch); ch = getchar()) sum = (sum << 3) + (sum << 1) + ch - '0';
  return sum * fl;
}
inline void proc_status() {
  ifstream t("/proc/self/status");
  cerr << string(istreambuf_iterator<char>(t), istreambuf_iterator<char>())
       << endl;
}
const int Maxn = 2e5 + 100;
int N, M;
map<pair<int, int>, int> Map, S;
struct opt {
  int op, first, second, ban;
  int l[2], r[2];
} Q[Maxn];
int ans;
inline int trans(int first, int k) { return (first + k - 1) % N + 1; }
namespace DSU {
int fa[Maxn], size[Maxn], top;
struct edge {
  int first, second, f;
} stk[Maxn];
inline void init() {
  for (int i = 1; i <= N; ++i) fa[i] = i, size[i] = 1;
}
inline int get_fa(int first) {
  return fa[first] == first ? first : get_fa(fa[first]);
}
inline void link(int first, int second) {
  first = get_fa(first), second = get_fa(second);
  if (size[first] < size[second]) swap(first, second);
  stk[++top] = (edge){first, second, fa[second]};
  if (first != second) fa[second] = first, size[first] += size[second];
}
inline void pop() {
  int first = stk[top].first, second = stk[top].second, f = stk[top].f;
  --top;
  size[first] -= size[second];
  fa[second] = f;
}
inline int query(int first, int second) {
  return get_fa(first) == get_fa(second);
}
}  // namespace DSU
namespace SEG {
vector<pair<int, int> > node[Maxn << 2];
inline void update(int o, int l, int r, int first, int second,
                   pair<int, int> val) {
  if (first > second) return;
  if (first <= l && r <= second) return void(node[o].push_back(val));
  if (first <= ((l + r) >> 1))
    update(o << 1, l, ((l + r) >> 1), first, second, val);
  if (second > ((l + r) >> 1))
    update(o << 1 | 1, ((l + r) >> 1) + 1, r, first, second, val);
}
inline void solve(int o, int l, int r) {
  for (int i = 0; i < node[o].size(); ++i)
    DSU ::link(node[o][i].first, node[o][i].second);
  if (l == r) {
    if (Q[l].op == 2)
      printf("%d", ans = DSU ::query(trans(Q[l].first, ans),
                                     trans(Q[l].second, ans)));
    else {
      for (int k = 0; k < 2; ++k) {
        if (Q[l].ban && ans != k) continue;
        int first = trans(Q[l].first, k), second = trans(Q[l].second, k);
        if (first > second) swap(first, second);
        if (ans == k) S[make_pair(first, second)] ^= 1;
        if (S[make_pair(first, second)])
          SEG ::update(1, 1, M, Q[l].l[k], Q[l].r[k], make_pair(first, second));
      }
    }
  } else
    solve(o << 1, l, ((l + r) >> 1)), solve(o << 1 | 1, ((l + r) >> 1) + 1, r);
  for (int i = 0; i < node[o].size(); ++i) DSU ::pop();
}
}  // namespace SEG
inline void Solve() {
  for (int i = M; i >= 1; --i) {
    if (Q[i].op == 2) continue;
    for (int k = 0; k < 2; ++k) {
      int first = trans(Q[i].first, k), second = trans(Q[i].second, k);
      if (first > second) swap(first, second);
      Q[i].l[k] = i + 1, Q[i].r[k] = M;
      if (Map[make_pair(first, second)]) {
        if (Map[make_pair(first, second)] == i)
          Q[i].ban = 1, Q[i].r[k] = Q[i].r[!k];
        else
          Q[i].r[k] = Map[make_pair(first, second)];
      }
      Map[make_pair(first, second)] = i;
    }
  }
  DSU ::init();
  SEG ::solve(1, 1, M);
}
inline void Input() {
  N = read<int>(), M = read<int>();
  for (int i = 1; i <= M; ++i)
    Q[i].op = read<int>(), Q[i].first = read<int>(), Q[i].second = read<int>();
}
int main() {
  Input();
  Solve();
  return 0;
}
