#include <bits/stdc++.h>
using namespace std;
const int MOD = 1000000007;
template <class T>
typename T::value_type arr_sum(const T& v, int n) {
  typename T::value_type sum = 0;
  for (int i = (0); i < (n); ++i) sum += v[i];
  return sum;
}
struct Sync_stdio {
  Sync_stdio() {
    cin.tie(NULL);
    ios_base::sync_with_stdio(false);
  }
} _sync_stdio;
vector<int> parent;
vector<int> r;
void make_set(int v) {
  parent[v] = v;
  r[v] = 1;
}
int find_set(int t) {
  if (t == parent[t]) {
    return t;
  }
  return parent[t] = find_set(parent[t]);
}
void union_sets(int a, int b) {
  a = find_set(a);
  b = find_set(b);
  if (a != b) {
    if (r[a] < r[b]) {
      swap(a, b);
    }
    parent[b] = a;
    if (r[a] == r[b]) {
      ++r[a];
    }
  }
}
int main() {
  int n, q;
  cin >> n >> q;
  r.resize(n);
  parent.resize(n);
  set<int> s;
  map<int, int> m;
  for (int i = (0); i < (n); ++i) {
    make_set(i);
    s.insert(i);
    m[i] = i;
  }
  for (int i = (0); i < (q); ++i) {
    int x, a, b;
    cin >> x >> a >> b;
    --a;
    --b;
    auto a1 = s.upper_bound(a);
    auto b1 = s.upper_bound(b);
    --a1;
    --b1;
    if (x == 2) {
      auto pos = s.lower_bound(*a1);
      auto start = pos;
      while (pos != s.end() && *pos <= *b1) {
        union_sets(*pos, *start);
        auto pose = pos;
        ++pos;
        if (pose == start) {
          continue;
        }
        s.erase(pose);
      }
      m[*start] = find_set(*start);
    } else if (x == 1) {
      union_sets(m[*a1], m[*b1]);
    } else {
      if (find_set(m[*a1]) == find_set(m[*b1])) {
        cout << "YES"
             << "\n";
      } else {
        cout << "NO"
             << "\n";
      }
    }
  }
}
