#include <bits/stdc++.h>
using namespace std;
const int P = 200, N = 4e5 + 5;
string ans;
struct Q {
  int t, x, y;
};
bool inGameE[N], inGameV[N];
vector<pair<int, int>> edges;
int n, m, last = 0;
int w[N], mem[N], isOn[N];
int findSet(int v) { return w[v] < 0 ? v : w[v] = findSet(w[v]); }
void connect(int a, int b) {
  a = findSet(a);
  b = findSet(b);
  if (a != b) {
    if (!inGameV[a] && !inGameV[b]) {
      if (w[a] > w[b]) swap(a, b);
      w[a] += w[b];
    } else if (inGameV[b]) {
      swap(a, b);
    }
    w[b] = a;
  }
}
void solve(vector<Q> block) {
  fill(inGameE, inGameE + edges.size(), 0);
  fill(inGameV, inGameV + n, 0);
  fill(w, w + n, -1);
  for (Q q : block) {
    if (q.t == 0) {
      inGameE[q.x] = inGameE[q.y] = 1;
    } else {
      inGameV[q.x] = inGameV[q.y] = 1;
    }
  }
  vector<int> edgesInGame, verticesInGame;
  for (int i = 0; i < edges.size(); i++) {
    if (inGameE[i]) {
      inGameV[edges[i].first] = 1;
      inGameV[edges[i].second] = 1;
      edgesInGame.push_back(i);
    }
  }
  for (int i = 0; i < edges.size(); i++) {
    if (!inGameE[i]) {
      if (isOn[i]) connect(edges[i].first, edges[i].second);
    }
  }
  for (int i = 0; i < n; i++) {
    if (inGameV[i]) {
      verticesInGame.push_back(i);
      mem[i] = w[i];
    }
  }
  for (Q q : block) {
    if (q.t) {
      q.x = (q.x + last) % n;
      q.y = (q.y + last) % n;
      for (int x : verticesInGame) {
        w[x] = mem[x];
      }
      for (int x : edgesInGame) {
        if (isOn[x]) {
          connect(edges[x].first, edges[x].second);
        }
      }
      if (findSet(q.x) == findSet(q.y))
        ans.push_back('1');
      else
        ans.push_back('0');
      last = ans.back() - '0';
    } else if (last) {
      isOn[q.y] ^= 1;
    } else {
      isOn[q.x] ^= 1;
    }
  }
}
signed main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cin >> n >> m;
  vector<vector<int>> queries;
  for (int i = 0; i < m; i++) {
    int type, x, y;
    cin >> type >> x >> y;
    x--, y--;
    if (x > y) swap(x, y);
    queries.push_back({type, x, y});
    if (type == 1) {
      edges.push_back({x, y});
      edges.push_back({(x + 1) % n, (y + 1) % n});
    }
  }
  for (auto &p : edges) {
    if (p.first > p.second) swap(p.first, p.second);
  }
  sort(edges.begin(), edges.end());
  edges.erase(unique(edges.begin(), edges.end()), edges.end());
  vector<Q> block;
  for (int i = 0; i < m; i++) {
    auto &q = queries[i];
    if (q[0] == 1) {
      pair<int, int> e = {q[1], q[2]};
      int x = lower_bound(edges.begin(), edges.end(), e) - edges.begin();
      e.first = (e.first + 1) % n;
      e.second = (e.second + 1) % n;
      if (e.first > e.second) swap(e.first, e.second);
      int y = lower_bound(edges.begin(), edges.end(), e) - edges.begin();
      block.push_back({0, x, y});
    } else {
      block.push_back({1, q[1], q[2]});
    }
    if (i == m - 1 || block.size() >= P) {
      solve(block);
      block.clear();
    }
  }
  cout << ans;
  return 0;
}
