package graphWars;

import java.util.Random;
import java.util.Scanner;

public class Gw {
	
	public static void baga ( int x , int y , Treap[] t , MinAint arb1 , MaxAint arb2 , int[] now1 , int [] now2 ){
		
		t[x].insert(y);
		int minim = t[x].getMin();
		int maxim = t[x].getMax();
		
		if ( minim != now1[x] ){
			now1[x] = minim;
			arb1.update(x, minim);
		}
		if ( maxim != now2[x] ){
			now2[x] = maxim;
			arb2.update(x, maxim);
		}
	}

	public static void scoate ( int x , int y , Treap[] t , MinAint arb1 , MaxAint arb2 , int[] now1 , int [] now2 ){
		
		t[x].delete(y);
		int minim = t[x].getMin();
		int maxim = t[x].getMax();
		
		if ( minim != now1[x] ){
			now1[x] = minim;
			arb1.update(x, minim);
		}
		if ( maxim != now2[x] ){
			now2[x] = maxim;
			arb2.update(x, maxim);
		}
	}
	
	public static void main (String[] args){
		
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt(),m = sc.nextInt();
		
		int now1[] = new int[n+1],now2[] = new int[n+1];
		int insertedx[] = new int[m+1],insertedy[] = new int[m+1],inserted = 0;
		MinAint aintmin = new MinAint(n);
		MaxAint aintmax = new MaxAint(n);
		
		for ( int i = 1 ; i <= n ; ++i ){
			now1[i] = Integer.MAX_VALUE;
			aintmin.update(i, Integer.MAX_VALUE);
		}
		
		Treap[] t = new Treap[n+1];
		for ( int i = 1 ; i <= n ; ++i ){
			t[i] = new Treap();
		}
		
		for ( int step = 1 ; step <= m ; ++step ){
			int type = sc.nextInt(),x,y;
			
			if ( type == 1 ){
				x = sc.nextInt();
				y = sc.nextInt();
				
				baga(x,y,t,aintmin,aintmax,now1,now2);
				baga(y,x,t,aintmin,aintmax,now1,now2);
				
				++inserted;
				insertedx[inserted] = x;
				insertedy[inserted] = y;
			}
			if ( type == 2 ){
				int ind = sc.nextInt();
				x = insertedx[ind];
				y = insertedy[ind];
				
				scoate(x,y,t,aintmin,aintmax,now1,now2);
				scoate(y,x,t,aintmin,aintmax,now1,now2);
			}
			if ( type == 3 ){
				x = sc.nextInt();
				y = sc.nextInt();
				
				int minim = aintmin.query(x, y);
				int maxim = aintmax.query(x, y);
				
				if ( minim >= x && maxim <= y ){
					System.out.println("YES");
				}
				else{
					System.out.println("NO");
				}
			}
		}
		
		sc.close();
	}
	
	static class MinAint{
		
		private int n;
		private int arb[];
		
		MinAint ( int n ){
			this.n = n;
			arb = new int[4*n+1];
			for ( int i = 1 ; i <= 4*n ; ++i ){
				arb[i] = Integer.MAX_VALUE;
			}
		}
		
		public void update ( int poz , int value ){
			update(1,1,n,poz,value);
		}
		
		public int query ( int left , int right ){
			return query(1,1,n,left,right);
		}
		
		private void update ( int nod , int st , int dr , int poz , int value ){
			
			if ( st == dr ){
				arb[nod] = value;
				return ;
			}
			
			int mij		= (st+dr)>>1;
			int nodst	= nod<<1;
			int noddr	= nodst | 1;
			
			if ( poz <= mij ){
				update(nodst,st,mij,poz,value);
			}
			else{
				update(noddr,mij+1,dr,poz,value);
			}
			
			arb[nod] = Math.min(arb[nodst],arb[noddr]);
		}
		
		int query ( int nod , int st , int dr , int left , int right ){
			
			if ( left <= st && dr <= right ){
				return arb[nod];
			}
			
			int mij		= (st+dr)>>1;
			int nodst	= nod<<1;
			int noddr	= nodst | 1;
			
			int r = Integer.MAX_VALUE;
			if ( left <= mij ){
				r = Math.min(r,query(nodst,st,mij,left,right));
			}
			if ( right > mij ){
				r = Math.min(r,query(noddr,mij+1,dr,left,right));
			}
			return r;
		}
	}
	
	static class MaxAint{
		
		private int n;
		private int arb[];
		
		MaxAint ( int n ){
			this.n = n;
			arb = new int[4*n+1];
		}
		
		public void update ( int poz , int value ){
			update(1,1,n,poz,value);
		}
		
		public int query ( int left , int right ){
			return query(1,1,n,left,right);
		}
		
		private void update ( int nod , int st , int dr , int poz , int value ){
			
			if ( st == dr ){
				arb[nod] = value;
				return ;
			}
			
			int mij		= (st+dr)>>1;
			int nodst	= nod<<1;
			int noddr	= nodst | 1;
			
			if ( poz <= mij ){
				update(nodst,st,mij,poz,value);
			}
			else{
				update(noddr,mij+1,dr,poz,value);
			}
			
			arb[nod] = Math.max(arb[nodst],arb[noddr]);
		}
		
		int query ( int nod , int st , int dr , int left , int right ){
			
			if ( left <= st && dr <= right ){
				return arb[nod];
			}
			
			int mij		= (st+dr)>>1;
			int nodst	= nod<<1;
			int noddr	= nodst | 1;
			
			int r = 0;
			if ( left <= mij ){
				r = Math.max(r,query(nodst,st,mij,left,right));
			}
			if ( right > mij ){
				r = Math.max(r,query(noddr,mij+1,dr,left,right));
			}
			return r;
		}
	}
	
	static class Treap {
		
		private final TreapNode nul;
		private TreapNode rNode;
		Random random;
		
		Treap () {
			nul = new TreapNode();
			rNode = nul;
			random = new Random();
		}
		
		public int getMin () {
			return rNode.getMin();
		}
		public int getMax () {
			return rNode.getMax();
		}
		
		public void insert ( int value ){
			
			rNode = rNode.insert(value,random.nextInt(Integer.MAX_VALUE));
		}
		
		public void delete ( int value ){
			
			rNode = rNode.delete(value);
		}
		
		public void printt () {
			rNode.printt();
		}
		
		public class TreapNode {
			
			private int priority,key;
			TreapNode ls,rs;
			
			TreapNode () {
				priority = key = 0;
				ls = rs = nul;
			}
			
			TreapNode ( int priority , int key , TreapNode ls , TreapNode rs ){
				this.priority	= priority;
				this.key		= key;
				this.ls = ls; this.rs = rs;
			}
			
			@Override
			public TreapNode clone () {
				return new TreapNode(priority, key, ls, rs);
			}
			
			private TreapNode rotateLS () {
				TreapNode nextrsNode = new TreapNode(this.priority,this.key, this.ls.rs, this.rs);
				return new TreapNode(this.ls.priority,this.ls.key,this.ls.ls,nextrsNode);
			}
			
			private TreapNode rotateRS () {
				TreapNode nextlsNode = new TreapNode(this.priority, this.key, this.ls, this.rs.ls);
				return new TreapNode(this.rs.priority, this.rs.key, nextlsNode, this.rs.rs);
			}
			
			private TreapNode balance () {
				
				if ( ls.priority > this.priority ){
					return this.rotateLS();
				}
				else{
					if ( rs.priority > this.priority ){
						return this.rotateRS();
					}
				}
				
				return this;
			}
			
			private void printt () {
				
				if ( this.ls != nul ){
					this.ls.printt();
				}
				System.out.printf("%d ",this.key);
				if ( this.rs!= nul ){
					this.rs.printt();
				}
			}
			
			private int getMin () {
				//assert(this != nul):"empty tree in getmin";
				if ( this == nul ){
					return Integer.MAX_VALUE;
				}
				
				if ( this.ls == nul ){
					return this.key;
				}
				return this.ls.getMin();
			}
			private int getMax () {
				//assert(this != nul):"empty tree in getmin";
				if ( this == nul ){
					return 0;
				}
				
				if ( this.rs == nul ){
					return this.key;
				}
				return this.rs.getMax();
			}
			
			TreapNode insert ( int key , int priority ){
				
				if ( this == nul ){
					return new TreapNode(priority, key, nul, nul);
				}
				
				if ( this.key >= key ){
					return (new TreapNode(this.priority, this.key, ls.insert(key, priority) , rs)).balance();
				}
				else{
					return (new TreapNode(this.priority, this.key, ls , rs.insert(key, priority))).balance();
				}
			}
			
			TreapNode delete ( int key ){
				if ( this == nul )	return this;
				
				if ( key < this.key ){
					return new TreapNode(this.priority, this.key, this.ls.delete(key) , rs);
				}
				if ( key > this.key ){
					return new TreapNode(this.priority, this.key, ls, this.rs.delete(key));
				}
				
				//key == this.key
				if ( this.ls == nul && this.rs == nul ){
					return nul;
				}
				
				if ( this.ls.priority > this.rs.priority ){
					TreapNode rotated = this.rotateLS();
					return new TreapNode(rotated.priority, rotated.key, rotated.ls, rotated.rs.delete(key));
				}
				else{
					TreapNode rotated = this.rotateRS();
					return new TreapNode(rotated.priority, rotated.key, rotated.ls.delete(key), rotated.rs);
				}
			}
		}
	}
}