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

public class prog {
	
	public static void baga ( int x , int y , Object[] tr , MinAint arb1 , MaxAint arb2 , int[] now1 , int [] now2 ){
		
		AvlTree<Integer,Integer>t = (AvlTree<Integer,Integer>)tr[x];
		t.insert(y,y);
		int minim = t.getMinKey();
		int maxim = t.getMaxKey();
		
		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 , Object[] tr , MinAint arb1 , MaxAint arb2 , int[] now1 , int [] now2 ){
		
		AvlTree<Integer,Integer>t = (AvlTree<Integer,Integer>)tr[x];
		t.delete(y);
		int minim = t.getMinKey();
		int maxim = t.getMaxKey();
		
		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);
		}
		
		Object[] t = new Object[n+1];
		for ( int i = 1 ; i <= n ; ++i ){
			t[i] = new AvlTree<Integer,Integer>();
		}
		
		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 AvlNode<T extends Comparable<T>,K> {
		
		T key;
		int height;
		private K value;
		AvlNode<T,K> lson,rson;
		
		public AvlNode () {
			key = null; value = null; height = 0;
			lson = rson = null;
		}
		public AvlNode ( T key , K value , AvlNode<T,K> lson , AvlNode<T,K> rson ){
			this.key = key;
			this.value = value;
			this.lson = lson;
			this.rson = rson;
			updateHeight();
		}
		
		private void updateHeight () {
			int h1 = lson != null ? lson.height : 0;
			int h2 = rson != null ? rson.height : 0;
			this.height = 1 + (h1 >= h2 ? h1 : h2);
		}
		private static int getHeight ( AvlNode<?,?> node ){
			if ( node == null )		return 0;
			return node.height;
		}
		
		public void setLson ( AvlNode<T,K> lson ){
			this.lson = lson;
			updateHeight();
		}
		public void setRson ( AvlNode<T,K> rson ){
			this.rson = rson;
			updateHeight();
		}
		
		public AvlNode<T,K> rotateLeft () {
			if ( lson == null )		return this;
			
			AvlNode<T,K>aux = lson;
			setLson(lson.rson);
			aux.setRson(this);
			return aux;
		}
		public AvlNode<T,K> rotateRight () {
			if ( rson == null )		return this;
			
			AvlNode<T,K>aux = rson;
			setRson(rson.lson);
			aux.setLson(this);
			return aux;
		}
		public AvlNode<T,K> rotateLeftRight () {
			setLson(lson.rotateLeft());
			return rotateRight();
		}
		public AvlNode<T,K> rotateRightLeft () {
			setRson(rson.rotateRight());
			return rotateLeft();
		}
		
		public AvlNode<T,K> rebalance () {
			int hl = getHeight(lson),hr = getHeight(rson);
			if ( hl <= hr-2 ){
				int hrl = getHeight(rson.lson),hrr = getHeight(rson.rson);
				
				if ( hrl > hrr )	return rotateRightLeft();
				else				return rotateRight();
			}
			else{
				if ( hl >= hr+2 ){
					int hll = getHeight(lson.lson),hlr = getHeight(lson.rson);
					
					if ( hll < hlr )	return rotateLeftRight();
					else				return rotateLeft();
				}
			}
			return this;
		}
	}
	
	static class AvlTree<T extends Comparable<T>,K> {
		
		AvlNode<T,K> root;
		
		public void insert ( T key , K value ){
			root = insertAVL(root,key,value);
		}
		public T getMinKey (){
			return getMinAVL(root);
		}
		public T getMaxKey () {
			return getMaxAVL(root);
		}
		public void delete ( T key ){
			root = deleteAVL(root,key);
		}
		
		private AvlNode<T,K> insertAVL ( AvlNode<T,K>node , T key , K value ){
			if ( node == null ){
				return new AvlNode<T,K>(key,value,null,null);
			}
			
			if ( key.compareTo(node.key) <= 0 ){
				node.setLson(insertAVL(node.lson,key,value));
			}
			else{
				node.setRson(insertAVL(node.rson,key,value));
			}
			
			return node.rebalance();
		}
		
		private AvlNode<T,K> deleteAVL ( AvlNode<T,K>node , T key ){
			if ( node == null )		return null;
			
			if ( key.compareTo(node.key) == 0 ){
				return deleteAVLNode(node);
			}
			
			if ( key.compareTo(node.key) < 0 ){
				node.setLson(deleteAVL(node.lson,key));
			}
			else{
				node.setRson(deleteAVL(node.rson,key));
			}
			return node.rebalance();
		}
		private AvlNode<T,K> deleteAVLNode ( AvlNode<T,K> node ){
			
			if ( node.lson == null )	return node.rson;
			if ( node.rson == null )	return node.lson;
			
			AvlNode<T,K> replacementNode = findLeftMost(node.rson);
			AvlNode<T,K> newRight = deleteLeftMost(node.rson);
			replacementNode.setLson(node.lson);
			replacementNode.setRson(newRight);
			
			return replacementNode.rebalance();
		}
		
		private AvlNode<T,K> findLeftMost ( AvlNode<T,K> node ){
			if ( node.lson == null )	return node;
			return findLeftMost(node.lson);
		}
		private AvlNode<T,K> deleteLeftMost ( AvlNode<T,K> node ){
			if ( node.lson == null )	return node.rson;
			return deleteLeftMost(node.lson).rebalance();
		}
		
		private T getMinAVL ( AvlNode<T,K>node ){
			
			if ( node.lson == null )	return node.key;
			return getMinAVL(node.lson);
		}
		private T getMaxAVL ( AvlNode<T,K>node ){
			
			if ( node.rson == null )	return node.key;
			return getMaxAVL(node.rson);
		}
	}

}