#include <bits/stdc++.h>
using namespace std;
int par[200010];
int rrank[200010];
int ffind(int x) {
  int root = par[x];
  if (par[x] != x) {
    root = ffind(par[x]);
    par[x] = root;
  }
  return root;
}
void merg(int a, int b) {
  int ra = ffind(a);
  int rb = ffind(b);
  if (rrank[ra] < rrank[rb]) {
    par[ra] = rb;
  } else if (rrank[ra] > rrank[rb]) {
    par[rb] = ra;
  } else {
    par[ra] = rb;
    rrank[rb]++;
  }
}
struct nodeS {
  int l;
  int r;
  nodeS* nl;
  nodeS* nr;
  bool isSame;
};
nodeS* segment_root;
nodeS* buildSegmentTree(int l, int r) {
  if (l == r) return NULL;
  nodeS* node = (nodeS*)calloc(sizeof(nodeS), 1);
  node->l = l;
  node->r = r;
  node->nl = node->nr = NULL;
  node->isSame = false;
  if (l + 1 == r) {
    node->isSame = true;
    return node;
  }
  int mid = ((l + r) / 2);
  if (mid > l) node->nl = buildSegmentTree(l, mid);
  if (mid < r) node->nr = buildSegmentTree(mid, r);
  return node;
}
bool mergeSegment(nodeS* node, int l, int r) {
  if (node == NULL) return false;
  if (node->isSame) return false;
  if (l <= node->l && node->r <= r) {
    for (int i = node->l; i < node->r - 1; i++) {
      merg(i, i + 1);
    }
    node->isSame = true;
    return true;
  }
  if (node->r <= l || node->l >= r) return false;
  mergeSegment(node->nl, l, r);
  mergeSegment(node->nr, l, r);
  if (node->nl != NULL && node->nr != NULL && l <= node->nl->r - 1 &&
      node->nr->l < r)
    merg(node->nl->r - 1, node->nr->l);
  return true;
}
int main() {
  int n, q;
  scanf("%d %d", &n, &q);
  for (int i = 0; i < n; i++) {
    rrank[i] = 0;
    par[i] = i;
  }
  segment_root = buildSegmentTree(0, n);
  for (int i = 0; i < q; i++) {
    int x, a, b;
    scanf("%d %d %d", &x, &a, &b);
    a--;
    b--;
    if (x == 1) {
      merg(a, b);
    } else if (x == 2) {
      mergeSegment(segment_root, a, b + 1);
    } else {
      if (ffind(a) == ffind(b)) {
        printf("YES\n");
      } else {
        printf("NO\n");
      }
    }
  }
}
