#include <bits/stdc++.h>
using namespace std;
struct union_find {
  vector<int> p;
  vector<tuple<int, int, int>> s;
  union_find(int n) : p(n, -1) {}
  bool join(int u, int v) {
    if ((u = root(u)) == (v = root(v))) {
      s.push_back({-1, 0, 0});
      return false;
    }
    if (p[u] > p[v]) swap(u, v);
    s.push_back({u, v, p[v]});
    p[u] += p[v];
    p[v] = u;
    return true;
  }
  void undo() {
    if (get<0>(s.back()) != -1) {
      int u, v, pv;
      tie(u, v, pv) = s.back();
      p[v] = pv;
      p[u] -= pv;
    }
    s.pop_back();
  }
  int root(int u) { return p[u] < 0 ? u : root(p[u]); }
};
struct query {
  int id, t, x, y;
};
struct info {
  int x, y, l, r;
  bool operator<(const info &o) const {
    return make_tuple(x, y, l, r) < make_tuple(o.x, o.y, o.l, o.r);
  }
};
int main() {
  ios_base::sync_with_stdio(0), cin.tie(0);
  int n, m;
  cin >> n >> m;
  vector<query> queries(m);
  map<pair<int, int>, vector<int>> times;
  for (auto &i : queries) {
    cin >> i.t >> i.x >> i.y;
    i.id = &i - &queries[0];
    if (i.t == 1) {
      if (i.x % n > i.y % n) swap(i.x, i.y);
      times[{i.x % n, i.y % n}].push_back(~i.id);
      if (i.x > i.y) swap(i.x, i.y);
      times[{i.x - 1, i.y - 1}].push_back(i.id);
    }
  }
  auto get = [&](int x) {
    if (x < 0) return ~x;
    return x;
  };
  vector<bool> obliged(m);
  vector<info> v;
  for (auto &i : times) {
    int sz = i.second.size();
    i.second.push_back(m);
    for (int j = 0; j < sz; ++j) {
      if (get(i.second[j]) == get(i.second[j + 1])) {
        ++j;
        obliged[i.second[j]] = true;
      }
      v.push_back(
          {i.first.first, i.first.second, i.second[j], i.second[j + 1]});
    }
  }
  union_find uf(n);
  vector<int> ans(m);
  set<pair<int, int>> alive;
  set<info> ftime;
  auto state = [&](int x) {
    if (x < 0) return 0;
    return ans[x];
  };
  function<void(int, int, vector<info> &)> f = [&](int l, int r,
                                                   vector<info> &q) {
    int md = (l + r) >> 1;
    vector<info> left, right;
    int undo = 0;
    for (auto i : q) {
      if (get(i.l) <= l && r <= get(i.r)) {
        bool take = (state(get(i.l) - 1) == (i.l < 0) || obliged[get(i.l)]) &&
                    ftime.find(i) == ftime.end();
        ftime.insert(i);
        if (take) {
          if (alive.find({i.x, i.y}) == alive.end())
            uf.join(i.x, i.y), ++undo, alive.insert({i.x, i.y});
          else
            alive.erase({i.x, i.y});
        } else {
          if (alive.find({i.x, i.y}) != alive.end()) uf.join(i.x, i.y), ++undo;
        }
      } else {
        if (get(i.l) < md) left.push_back(i);
        if (md < get(i.r)) right.push_back(i);
      }
    }
    if (l + 1 != r) {
      f(l, md, left);
      f(md, r, right);
    } else {
      if (queries[l].t == 2) {
        bool w = !state(l - 1);
        ans[l] =
            uf.root((queries[l].x - w) % n) == uf.root((queries[l].y - w) % n);
        cout << ans[l];
      } else
        ans[l] = state(l - 1);
    }
    while (undo--) uf.undo();
  };
  f(0, m, v);
  cout << "\n";
  return 0;
}
