#include <bits/stdc++.h>
using namespace std;
template <typename T>
inline void read(T &x) {
  T f = 1;
  x = 0;
  char ch = getchar();
  while (0 == isdigit(ch)) {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (0 != isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar();
  x *= f;
}
template <typename T>
inline void write(T x) {
  if (x < 0) {
    x = ~(x - 1);
    putchar('-');
  }
  if (x > 9) write(x / 10);
  putchar(x % 10 + '0');
}
const int inf = 0x3f3f3f3f;
const int N = 2e5 + 100;
struct Qu {
  int op, x, y;
} q[N];
map<pair<int, int>, int> mp;
int f[N], rk[N], ans[N], last, n, m;
struct revo {
  int fax, fay;
  int rkx, rky;
};
struct Node {
  int l, r;
  vector<pair<int, int>> node;
} tree[N << 2];
int find(int x) { return f[x] == x ? x : find(f[x]); }
revo merge(int x, int y) {
  revo ans;
  int xx = find(x), yy = find(y);
  ans.fax = xx, ans.fay = yy;
  ans.rkx = rk[xx], ans.rky = rk[yy];
  if (xx != yy) {
    if (rk[xx] > rk[yy]) swap(xx, yy);
    f[xx] = yy;
    rk[yy] = max(rk[yy], rk[xx] + 1);
  }
  return ans;
}
void revocation(stack<revo> &st) {
  while (st.size()) {
    revo a = st.top();
    f[a.fax] = a.fax, f[a.fay] = a.fay;
    rk[a.fax] = a.rkx, rk[a.fay] = a.rky;
    st.pop();
  }
}
void build(int k, int l, int r) {
  tree[k].l = l, tree[k].r = r;
  if (l == r) return;
  int mid = (l + r) >> 1;
  build(k << 1, l, mid), build(k << 1 | 1, mid + 1, r);
}
void update(int k, int l, int r, pair<int, int> val) {
  if (l > r) return;
  if (tree[k].l > r || tree[k].r < l) return;
  if (tree[k].l >= l && tree[k].r <= r) {
    tree[k].node.push_back(val);
    return;
  }
  update(k << 1, l, r, val), update(k << 1 | 1, l, r, val);
}
void dfs(int k) {
  stack<revo> st;
  for (auto it : tree[k].node)
    if (mp[it]) st.push(merge(it.first, it.second));
  if (tree[k].l == tree[k].r) {
    int id = tree[k].l;
    if (q[id].op == 2) last = ans[id] = (find(q[id].x) == find(q[id].y));
    q[id + 1].x = (q[id + 1].x + last - 1) % n + 1,
           q[id + 1].y = (q[id + 1].y + last - 1) % n + 1;
    if (q[id + 1].x > q[id + 1].y) swap(q[id + 1].x, q[id + 1].y);
    if (q[id + 1].op == 1) mp[{q[id + 1].x, q[id + 1].y}] ^= 1;
    revocation(st);
    return;
  } else
    dfs(k << 1), dfs(k << 1 | 1);
  revocation(st);
}
void init() {
  for (int i = 1; i < N; i++) f[i] = i, rk[i] = 1;
}
int main() {
  init();
  read(n), read(m);
  build(1, 1, m);
  for (int i = 1, x, y, op; i <= m; i++) {
    read(op), read(x), read(y);
    q[i] = {op, x, y};
    if (op == 2) continue;
    if (x > y) swap(x, y);
    if (mp[{x, y}])
      update(1, mp[{x, y}], i, {x, y}), mp[{x, y}] = i + 1;
    else
      mp[{x, y}] = i;
    x = x % n + 1, y = y % n + 1;
    if (x > y) swap(x, y);
    if (mp[{x, y}])
      update(1, mp[{x, y}], i, {x, y}), mp[{x, y}] = i + 1;
    else
      mp[{x, y}] = i;
  }
  for (auto it : mp)
    if (it.second <= m) update(1, it.second, m, it.first);
  mp.clear();
  if (q[1].op == 1) mp[{min(q[1].x, q[1].y), max(q[1].x, q[1].y)}] = 1;
  memset(ans, -1, sizeof(ans));
  dfs(1);
  for (int i = 1; i <= m; i++)
    if (ans[i] != -1) write(ans[i]);
  return 0;
}
