#include #include #include using namespace std; const int MAX = 100050; const int INF = 0x3f3f3f3f; #define PII pair #define minim first #define maxim second #define leftSon (nod << 1) #define rightSon ((nod << 1) | 1) #define x first #define y second int N, M; PII Limits[MAX], aInt[MAX << 2]; set G[MAX]; vector< PII > Edges; void Update(int nod, int L, int R, int target) { if(L == R) { aInt[nod] = Limits[target]; return; } int M = (L + R) >> 1; if(target <= M) Update(leftSon, L, M, target); else Update(rightSon, M + 1, R, target); aInt[nod].minim = min(aInt[leftSon].minim, aInt[rightSon].minim); aInt[nod].maxim = max(aInt[leftSon].maxim, aInt[rightSon].maxim); } PII Query(int nod, int L, int R, int Left, int Right) { if(Left <= L && R <= Right) return aInt[nod]; int M = (L + R) >> 1; PII Ans = make_pair(INF, -INF), Q; if(Left <= M) { Q = Query(leftSon, L, M, Left, Right); Ans.minim = min(Ans.minim, Q.minim); Ans.maxim = max(Ans.maxim, Q.maxim); } if(M < Right) { Q = Query(rightSon, M + 1, R, Left, Right); Ans.minim = min(Ans.minim, Q.minim); Ans.maxim = max(Ans.maxim, Q.maxim); } return Ans; } void Check(int nod) { set::iterator it = G[nod].begin(); bool changed = false; if(*it != Limits[nod].minim) { Limits[nod].minim = *it; changed = true; } it = G[nod].end(); --it; if(*it != Limits[nod].maxim) { Limits[nod].maxim = *it; changed = true; } if(changed) Update(1, 1, N, nod); } int main() { cin >> N >> M; for(int i = 1; i <= N; i++) { G[i].insert(i); Check(i); } for(int i = 1, op, A, B; i <= M; i++) { cin >> op; /* operatia de adaugare a unei muchii */ if(op == 1) { cin >> A >> B; Edges.push_back(make_pair(A, B)); G[A].insert(B); Check(A); G[B].insert(A); Check(B); } else if(op == 2) { //Sterg o muchie cin >> A; --A; G[Edges[A].x].erase(Edges[A].y); Check(Edges[A].x); G[Edges[A].y].erase(Edges[A].x); Check(Edges[A].y); } else { //Query cin >> A >> B; PII Ans = Query(1, 1, N, A, B); if(Ans.x >= A && Ans.y <= B) cout << "YES\n"; else cout << "NO\n"; } } }