#include <bits/stdc++.h>
using namespace std;
struct DS {
  vector<int> Parent;
  vector<int> Cont;
  vector<pair<int, int>> UndoCont;
  vector<pair<int, int>> UndoParent;
  void clear() {
    UndoCont.clear();
    UndoParent.clear();
    for (int i = 0; i < Parent.size(); i++) {
      Parent[i] = i;
      Cont[i] = 1;
    }
  }
  DS(int sz) {
    Parent = vector<int>(sz);
    Cont = vector<int>(sz);
    for (int i = 0; i < Parent.size(); i++) {
      Parent[i] = i;
      Cont[i] = 1;
    }
  }
  int SetOf(int x) {
    if (Parent[x] == x) return x;
    UndoParent.push_back(pair<int, int>(x, Parent[x]));
    return Parent[x] = SetOf(Parent[x]);
  }
  void Merge(int x, int y) {
    x = SetOf(x);
    y = SetOf(y);
    if (x == y) return;
    if (Cont[x] > Cont[y]) swap(x, y);
    UndoParent.push_back(pair<int, int>(x, Parent[x]));
    Parent[x] = y;
    UndoCont.push_back(pair<int, int>(y, Cont[y]));
    Cont[y] += Cont[x];
  }
  bool SameSet(int x, int y) { return SetOf(x) == SetOf(y); }
  void Undo() {
    while (!UndoParent.empty()) {
      Parent[UndoParent.back().first] = UndoParent.back().second;
      UndoParent.pop_back();
    }
    while (!UndoCont.empty()) {
      Cont[UndoCont.back().first] = UndoCont.back().second;
      UndoCont.pop_back();
    }
  }
};
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n, m;
  cin >> n >> m;
  vector<pair<int, pair<int, int>>> queries(m);
  for (auto &i : queries) {
    cin >> i.first >> i.second.first >> i.second.second;
    --i.second.first;
    --i.second.second;
  }
  int sqt = (int)sqrt(m) + 1;
  vector<vector<pair<int, pair<int, int>>>> q;
  for (int i = 0; i < m;) {
    q.push_back(vector<pair<int, pair<int, int>>>());
    while (i < m && q.back().size() < sqt) {
      q.back().push_back(queries[i]);
      ++i;
    }
  }
  DS ds(n);
  vector<bool> used(n);
  vector<pair<int, int>> fixededges;
  int last = 0;
  for (auto &i : q) {
    ds.clear();
    for (int j = 0; j < n; j++) used[j] = false;
    for (auto &j : i)
      used[j.second.first] = used[j.second.second] =
          used[(j.second.first + 1) % n] = used[(j.second.second + 1) % n] =
              true;
    vector<pair<int, int>> exedges;
    set<pair<int, int>> addingEdges;
    for (auto &j : fixededges)
      if (!used[j.first] || !used[j.second])
        exedges.push_back(j);
      else
        addingEdges.insert(j);
    for (auto &j : exedges) ds.Merge(j.first, j.second);
    ds.UndoCont.clear();
    ds.UndoParent.clear();
    for (auto &j : i) {
      int x = (j.second.first + last) % n;
      int y = (j.second.second + last) % n;
      if (x > y) swap(x, y);
      if (j.first == 1) {
        if (addingEdges.count(pair<int, int>(x, y)))
          addingEdges.erase(pair<int, int>(x, y));
        else
          addingEdges.insert(pair<int, int>(x, y));
      } else {
        for (auto &k : addingEdges) ds.Merge(k.first, k.second);
        last = ds.SameSet(x, y);
        ds.Undo();
        cout << last;
      }
    }
    for (auto &j : addingEdges) exedges.push_back(j);
    swap(exedges, fixededges);
  }
  return 0;
}
