#include <bits/stdc++.h>
using namespace std;
inline int read() {
  int x = 0, f = 1;
  char c = getchar();
  for (; !isdigit(c); c = getchar())
    if (c == '-') f = -1;
  for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
  return x * f;
}
const int S = 5000;
const int maxn = 2e5 + 10;
namespace has {
template <class T>
inline void hash_c(size_t &seed, const T &v) {
  static hash<T> hasher;
  seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
}  // namespace has
namespace std {
template <>
struct hash<pair<int, int> > {
  size_t operator()(const pair<int, int> &pr) const {
    size_t seed(0);
    has::hash_c(seed, pr.first);
    has::hash_c(seed, pr.second);
    return seed;
  }
};
}  // namespace std
struct req {
  int o, x, y;
  pair<int, int> pr, nx;
} q[maxn];
int n, m, lst = 0;
unordered_set<pair<int, int> > st;
struct est {
  unordered_set<pair<int, int> > a;
  inline void clear() { a.clear(); }
  void modify(const pair<int, int> &pr) {
    unordered_set<pair<int, int> >::iterator it = a.find(pr);
    if (it == a.end())
      a.insert(pr);
    else
      a.erase(it);
  }
} nt, mt;
namespace graph {
vector<int> g[maxn], h[maxn];
int cls, col[maxn], tic[maxn], tim = 0;
int des;
void clear() {
  cls = 0;
  for (int i = 1; i <= n; ++i) {
    g[i].clear();
    col[i] = 0;
  }
}
inline void add(vector<int> g[], int x, int y) {
  g[x].push_back(y);
  g[y].push_back(x);
}
void dfs(int x) {
  col[x] = cls;
  for (int v : g[x])
    if (!col[v]) dfs(v);
}
void prepare() {
  for (const pair<int, int> &pr : nt.a) add(g, pr.first, pr.second);
  for (int i = 1; i <= n; ++i)
    if (!col[i]) ++cls, dfs(i);
}
int go(int x) {
  if (x == des) return 1;
  tic[x] = tim;
  for (int v : h[x])
    if (tic[v] != tim && go(v)) return 1;
  return 0;
}
int work(const pair<int, int> &as) {
  if (col[as.first] == col[as.second]) return 1;
  h[col[as.first]].clear(), h[col[as.second]].clear();
  for (const pair<int, int> &pr : mt.a)
    h[col[pr.first]].clear(), h[col[pr.second]].clear();
  for (const pair<int, int> &pr : mt.a) add(h, col[pr.first], col[pr.second]);
  ++tim, des = col[as.second];
  return go(col[as.first]);
}
}  // namespace graph
void check(const pair<int, int> &pr) {
  unordered_set<pair<int, int> >::iterator it = nt.a.find(pr);
  if (it != nt.a.end()) nt.a.erase(it), mt.a.insert(pr);
}
int main() {
  n = read(), m = read();
  for (int i = 1; i <= m; ++i) {
    q[i].o = read();
    int x = q[i].x = read(), y = q[i].y = read();
    if (x > y) swap(x, y);
    q[i].pr = pair<int, int>(x, y);
    x = x % n + 1, y = y % n + 1;
    if (x > y) swap(x, y);
    q[i].nx = pair<int, int>(x, y);
  }
  for (int i = 1, j; i <= m; i = j) {
    j = min(m + 1, i + S);
    for (const pair<int, int> &pr : mt.a) nt.a.insert(pr);
    mt.clear();
    for (int k = i; k < j; ++k)
      if (q[k].o == 1) {
        check(q[k].pr);
        check(q[k].nx);
      }
    graph::clear();
    graph::prepare();
    for (int k = i; k < j; ++k) {
      int &x = q[k].x, &y = q[k].y;
      if (lst) x = x % n + 1, y = y % n + 1, swap(q[k].pr, q[k].nx);
      if (x > y) swap(x, y);
      if (q[k].o == 1)
        mt.modify(q[k].pr);
      else if (q[k].o == 2)
        printf("%d", lst = graph::work(q[k].pr));
    }
  }
  puts("");
  return 0;
}
