#include <cassert>

#include <algorithm>
#include <fstream>
#include <iostream>
#include <set>
#include <vector>
using namespace std;
typedef pair<int, int> pere;
const int MAX_N = 100005;

set<int> graph[MAX_N];
vector<pere> edges;
pere neigh[MAX_N];
pere stree[MAX_N * 4];
int n;

void update(int node, int left, int right, int index) {
    if(left == right) {
        stree[node] = neigh[index];
    } else {
        int middle = (left + right) / 2;
        if(index <= middle) {
            update(2 * node, left, middle, index);
        } else {
            update(2 * node + 1, middle + 1, right, index);
        }
        stree[node].first = min(stree[2 * node].first, stree[2 * node + 1].first);
        stree[node].second = max(stree[2 * node].second, stree[2 * node + 1].second);
    }
}
pere query(int node, int left, int right, int qleft, int qright) {
    if(qleft <= left && right <= qright) {
        return stree[node];
    }
    int middle = (left + right) / 2;
    pere answer(n + 1, 0);
    if(qleft <= middle) {
        pere aux = query(2 * node, left, middle, qleft, qright);
        answer.first = min(answer.first, aux.first);
        answer.second = max(answer.second, aux.second);
    }
    if(qright > middle) {
        pere aux = query(2 * node + 1, middle + 1, right, qleft, qright);
        answer.first = min(answer.first, aux.first);
        answer.second = max(answer.second, aux.second);
    }
    return answer;
}

inline void update_node(int node) {
    set<int>::iterator it = graph[node].begin();
    bool changed = false;
    if(*it != neigh[node].first) {
        neigh[node].first = *it;
        changed = true;
    }
    it = graph[node].end(); --it;
    if(*it != neigh[node].second) {
        neigh[node].second = *it;
        changed = true;
    }
    if(changed) {
        update(1, 1, n, node);
    }
}

int main() {
//    ifstream cin("f.in");
    int m;
    cin >> n >> m;
    for(int i = 1; i <= n; ++ i) {
        graph[i].insert(i);
        update_node(i);
    }
    for(int i = 1; i <= m; ++ i) {
        int type, a, b;
        cin >> type;
        if(type == 1) {
            cin >> a >> b;
            edges.push_back(pere(a, b));
            graph[a].insert(b);
            graph[b].insert(a);
            update_node(a);
            update_node(b);
        } else if(type == 2) {
            cin >> a; -- a;
            graph[edges[a].first].erase(edges[a].second);
            graph[edges[a].second].erase(edges[a].first);
            update_node(edges[a].first);
            update_node(edges[a].second);
        } else {
            cin >> a >> b;
            pere answer = query(1, 1, n, a, b);
            if(a <= answer.first && answer.second <= b) {
                cout << "YES\n";
            } else {
                cout << "NO\n";
            }
        }
    }
    return 0;
}