In this problem at each moment you have a set of intervals. You can move from interval (a, b) from our set to interval (c, d) from our set if and only if c < a < d or c < b < d. Also there is a path from interval I_1 from our set to interval I_2 from our set if there is a sequence of successive moves starting from I_1 so that we can reach I_2.

Your program should handle the queries of the following two types:  "1 x y" (x < y) — add the new interval (x, y) to the set of intervals. The length of the new interval is guaranteed to be strictly greater than all the previous intervals. "2 a b" (a ≠ b) — answer the question: is there a path from a-th (one-based) added interval to b-th (one-based) added interval? 

Answer all the queries. Note, that initially you have an empty set of intervals.


-----Input-----

The first line of the input contains integer n denoting the number of queries, (1 ≤ n ≤ 100). Each of the following lines contains a query as described above. All numbers in the input are integers and don't exceed 10^9 by their absolute value.

It's guaranteed that all queries are correct.


-----Output-----

For each query of the second type print "YES" or "NO" on a separate line depending on the answer.


-----Examples-----
Input
5
1 1 5
1 5 11
2 1 2
1 2 9
2 1 2

Output
NO
YES

Difficulty: interview

Starter code:

Solutions:
#!/usr/bin/env python3

def is_conn(i1, i2):
  a, b = i1
  c, d = i2
  return (c < a < d or c < b < d)

neighbors = {}
intervals = []

n = int(input())
for i in range(0, n):
  q, x, y = [int(j) for j in input().split()]
  if q == 1:
    # we add to the interval
    ourint = (x,y)
    intervals.append(ourint)
    neighbors[ourint] = []
    # and check for edges
    for interval in intervals:
      # if they are connected, join them
      if is_conn(interval, ourint):
        neighbors[interval].append(ourint)
      if is_conn(ourint, interval):
        neighbors[ourint].append(interval)
    
  if q == 2:
    # we check whether there is a path from x to y
    # this is easy version, bfs should be enough
    x -= 1
    y -= 1
    a = intervals[x]
    b = intervals[y]
    
    visited = {a}
    query = [a]
    while len(query) > 0:
        j = query[0]
        query = query[1:]
        for nei in neighbors[j]:
            if not nei in visited:
                query.append(nei)
                visited = visited | {nei}

    if b in visited:
        print("YES")
    else:
        print("NO")     
            
              
    


def DFS(v,b,visited):
    visited.add(v)
    nonlocal count,matrix,ok
    if v==b:
        ok = True
        return
    for i in range(count):
        if matrix[v][i]==1 and v!=i and i not in visited:
            DFS(i,b,visited)


n  =  int(input())
matrix = [[0]*111 for i in range(111)]
count = 0
ok = False
intervals = []
for i in range(n):
    t,a,b  = list(map(int,input().split()))
    if t==1:
        intervals.append((a,b))
        for l in range(count):
            c,d = intervals[l]
            if c<a<d or c<b<d:
                matrix[count][l]=1
            if a<c<b or a<d<b:
                matrix[l][count]=1
        count+=1
    if t==2:
        visited = set()
        ok = False
        res = DFS(a-1,b-1,visited)
        if ok:print("YES")
        else:print("NO")



flag=False;
def main():
    intset=[]
    qr=int(input())
    for i in range(qr):
        qqss=str(input())
        qqss=qqss.split(" ")
        if qqss[0]=="1":
            a=int(qqss[1])
            b=int(qqss[2])
            intset.append([a,b]);
        else:
            si=int(qqss[1])
            fi=int(qqss[2])
            si-=1
            fi-=1
            v=[False for x in range(len(intset))]
            printIsPath(intset,si,fi,v)

def printIsPath(iset,a,b,v):
    ast=iset[a][0]
    aen=iset[a][1]
    bst=iset[b][0]
    ben=iset[b][1]
    if bst < ast < ben or bst < aen < ben:
        print ("YES")
        return;
    v[a]=True
    nonlocal flag;
    flag=False
    for i in range(len(iset)):
        mst=iset[i][0]
        men=iset[i][1]
        if  (mst < ast < men or mst < aen < men) and not v[i]:
            if searchFinal(iset,i,b,v):
                return;
    if not flag:
        print ("NO")

def searchFinal(iset,i,f,v):
    v[i]=True;
    if i==f:
        print ("YES")
        nonlocal flag;
        flag=True;
        return True
    ist=iset[i][0]
    ien=iset[i][1]
    for j in range(len(iset)):
        jst=iset[j][0]
        jen=iset[j][1]
        if not v[j] and (jst < ist < jen or jst < ien < jen):
            searchFinal(iset,j,f,v)

main()

data = []
for _ in range(int(input())):
    cmd = list(map(int, input().split()))
    if cmd[0] == 1:
        data.append(cmd[1:])
    else:
        done = [False] * (len(data) + 1)
        que = [cmd[1] - 1]
        while len(que):
            p = que[0]
            del que[0]
            for i, v in enumerate(data):
                if (v[0] < data[p][0] < v[1] or v[0] < data[p][1] < v[1]) and not done[i]:
                    done[i] = True
                    que.append(i)
        print("YES" if done[cmd[2] - 1] else "NO")




def get_operations():
    n = int(input())
    return [tuple(int(k) for k in input().split()) for _ in range(n)]

def can_move(a, b):
    x1, y1 = a
    x2, y2 = b
    return (x2 < x1 and x1 < y2) or (x2 < y1 and y1 < y2)

def can_reach(intervals, x, y, mask = []):
    if not mask:
        mask = [False] * len(intervals)
    if x == y:
        return True
    mask[x] = True
    xs = [k for k in range(len(intervals)) if not mask[k] and can_move(intervals[x], intervals[k])]
    return any(can_reach(intervals, k, y, mask) for k in xs)

def solve(operations):
    intervals = []
    results = []
    for op in operations:
        t, x, y = op
        if t == 1:
            intervals.append(tuple([x, y]))
        else:
            results.append(can_reach(intervals, x - 1, y - 1))
    return results

def __starting_point():
    operations = get_operations()
    results = solve(operations)
    for res in results:
        print('YES' if res else 'NO')

__starting_point()

path = []
n = int(input())
for it in range(0, n):
	data = list(map(int, input().split(' ')))
	if data[0] == 1:
		path.append(data[1:])
	else:
		vis = [False] * (len(path) + 1)
		que = [data[1] - 1]
		while len(que):
			p = que[0]
			del que[0]
			for i, v in enumerate(path):
				if (v[0] < path[p][0] < v[1] or v[0] < path[p][1] < v[1]) and not vis[i]:
					vis[i] = True
					que.append(i)
		print('YES' if vis[data[2] -1] else 'NO')

n = int(input())
xy = []
adjlist = []

def dfs(visit,cur,dest):
    visit[cur] = True
    if cur==dest: return True
    else:
        found = False
        for v in adjlist[cur] :
            if not visit[v] :
                found = found or dfs(visit,v,dest)
        return found

for tc in range(0,n):
    q, a, b = [int(x)-1 for x in input().split()]
    if q == 0:
        adjlist.append([])
        for i in range(0,len(xy)):
            x,y = xy[i]
            if (a<x<b or a<y<b):
                adjlist[i].append(len(xy))
            if (x<a<y or x<b<y):
                adjlist[len(xy)].append(i)
        xy.append((a,b))
    elif q == 1:
        visit = [False for x in range(0,len(xy))]
        if dfs(visit,a,b):
            print("YES")
        else:
            print("NO")


class Interval:
    def __init__(self, a, b):
        self.interval_a = a
        self.interval_b = b

    def can_go(self, interval):
        return (interval.interval_a < self.interval_a < interval.interval_b) or (
            interval.interval_a < self.interval_b < interval.interval_b)


intervals = []
matrix = []


def dfs(a, b, visited, matrix):
    if a == b:
        return True

    ans = False
    visited[a] = True
    for i in range(len(matrix)):
        if matrix[a][i] and not visited[i]:
            ans = ans or dfs(i, b, visited, matrix)
    return ans


for i in range(int(input())):
    t, a, b = list(map(int, input().split()))
    if t == 1:
        newInterval = Interval(a, b)
        intervals.append(newInterval)
        for row in range(len(matrix)):
            matrix[row].append(intervals[row].can_go(newInterval))
        matrix.append([])
        for col in range(len(matrix)):
            matrix[len(matrix) - 1].append(newInterval.can_go(intervals[col]))
    if t == 2:
        visited = []
        for i in range(len(intervals)):
            visited.append(False)
        if dfs(a - 1, b - 1, visited, matrix):
            print("YES")
        else:
            print("NO")









s, t, i = {}, [], 1
for n in range(int(input())):
    c, a, b = map(int, input().split())
    if c > 1: print('YES' if b in s[a] else 'NO')
    else:
        s[i] = {i}
        for j, (x, y) in enumerate(t, 1):
            if x < a < y or x < b < y: s[i].update(s[j])
        r = set(j for j, (x, y) in enumerate(t, 1) if a < x < b or a < y < b)
        for j in range(1, len(t) + 1):
            if r & s[j]: s[j].update(s[i])
        t.append((a, b))
        i += 1

s, t, i = {}, [], 1
for n in range(int(input())):
    c, a, b = map(int, input().split())
    if c > 1: print('YES' if b in s[a] else 'NO')
    else:
        s[i] = [i]
        for j, (x, y) in enumerate(t, 1):
            if x < a < y or x < b < y: s[i].extend(s[j])
        s[i] = set(s[i])
        r = [j for j, (x, y) in enumerate(t, 1) if a < x < b or a < y < b]
        for j in range(1, len(t) + 1):
            if any(k in s[j] for k in r): s[j].update(s[i])
        t.append((a, b))
        i += 1

def recursive_dfs(graph, start, path=[]):
  '''recursive depth first search from start'''
  path=path+[start]
  for node in graph[start]:
    if not node in path:
      path=recursive_dfs(graph, node, path)
  return path

def conn(x, y):
    a, b = x[0], x[1]
    c, d = y[0], y[1]
    return c < a < d or c < b < d

adj = {}
vert = []
n = int(input())
for i in range(n):
    a, b, c = list(map(int, input().split(' ')))
    if a == 1:
        incoming = (b, c)
        adj[incoming] = []
        for vertex in vert:
            if conn(vertex, incoming):
                adj[vertex].append(incoming)
            if conn(incoming, vertex):
                adj[incoming].append(vertex)
        vert.append(incoming)
        
    if a == 2:
        check = vert[b-1]
        in_chk = vert[c-1]
        if in_chk in recursive_dfs(adj, check):
            print("YES")
        else:
            print("NO")


s, t, i = {}, [], 1
for n in range(int(input())):
    c, a, b = map(int, input().split())
    if c > 1: print('YES' if b in s[a] else 'NO')
    else:
        s[i] = [i]
        for j, (x, y) in enumerate(t, 1):
            if x < a < y or x < b < y: s[i].extend(s[j])
        s[i] = set(s[i])
        r = [j for j, (x, y) in enumerate(t, 1) if a < x < b or a < y < b]
        for j in range(1, len(t) + 1):
            if any(k in s[j] for k in r): s[j].update(s[i])
        t.append((a, b))
        i += 1

visited = [0 for i in range(110)]
def reset():
	nonlocal N,visited
	for i in range(N):
		visited[i] = 0

def dfs(s,e):
	#print(s,e)
	nonlocal N,nodes,visited
	if(s==e):
		return True
	if(visited[s]==1):
		return False
	visited[s]=1
	ans = False
	for i in range(N):
		if(i==s):
			continue
		a = nodes[s][0]
		b = nodes[s][1]
		c = nodes[i][0]
		d = nodes[i][1]
		if((c<a and a<d) or (c<b and b<d)):
			ans = ans or dfs(i,e) 
	return ans

nodes = []
N = 0
M = int(input())
for k in range(M):
	com,u,v = tuple(int(i) for i in input().split())

	if(com==1):
		V = [u,v]
		nodes.append(V)
		N+=1
	else:
		u-=1
		v-=1
		reset()
		if(dfs(u,v)):
			print("YES")
		else:
			print("NO")

visited=[False]*105
p={}
def dfs(i):
    nonlocal visited
    nonlocal p
    if visited[i]==True:
        return
    visited[i]=True
    for j in p[i]:
        dfs(j)

def main():
    nonlocal visited
    nonlocal p
    mode="filee"
    if mode=="file":f=open("test.txt","r")
    get = lambda :[int(x) for x in (f.readline() if mode=="file" else input()).split()]
    [n]=get()
    g=[[0]]
    le = 0
    for z in range(n):
        [t,x,y]=get()
        if t==1:
            g.append([x,y])
            le+=1
            p[le]=[]
            for i in range(1,le):
                [a,b] = [g[i][0],g[i][1]]
                if (x<a and a<y) or (x<b and b<y):
                    p[i].append(le)
                if (a<x and x<b) or (a<y and y<b):
                    p[le].append(i)
        else:
            for i in range(105):
                visited[i]=False
            dfs(x)
            print("YES" if visited[y]==True else "NO")    

    if mode=="file":f.close()


def __starting_point():
    main()

__starting_point()

from operator import xor

def dfs(d, start, finish):
    visited = []
    temp = []
    while True:
        if start not in visited:
            visited.append(start)
            [temp.append(item) for item in d[start]]
        if not temp:
            return False
        temp.reverse()
        start = temp.pop()
        temp.reverse()
        if start == finish:
            return True

n = int(input())
dict = {}
list = []
for i in range(n):
    line = [int(item) for item in input().split()]
    if line[0] == 1:
        dict[(line[1], line[2])] = set()
        list.append((line[1], line[2]))
        for (a, b) in dict:
            if xor(line[1] < a and a < line[2], line[1] < b and b < line[2]):
                dict[(line[1], line[2])].add((a,b))
                dict[(a,b)].add((line[1], line[2]))
            if a > line[1] and b < line[2]:
                dict[(a,b)].add((line[1], line[2]))
    else:
        first = list[line[1]-1]
        finish = list[line[2]-1]
        if dfs(dict, first, finish):
            print('YES')
        else:
            print('NO')

def dfs(a, b, v, e):
    if a == b:
        return True
    v[a] = True
    for x in e[a]:
        if not v[x] and dfs(x, b, v, e):
            return True
    return False
a, e = [], []    
for i in range(int(input())):
    t, x, y = map(int, input().split())
    if t == 1:
        a.append((x, y))
        e.append([])
        for i, ai in enumerate(a):
            if x in range(ai[0] + 1, ai[1]) or y in range(ai[0] + 1, ai[1]):
                e[-1].append(i)
            if ai[0] in range(x + 1, y) or ai[1] in range(x + 1, y):
                e[i].append(len(a) - 1)
    else:
        print('YES' if dfs(x - 1, y - 1, [False] * len(a), e) else 'NO')

visited = [0 for i in range(110)]

def reset():
    nonlocal N , visited
    for i in range(N):
        visited[i] = 0

def dfs(s, e):
    nonlocal N, nodes, visited
    if s == e:
        return True
    if visited[s] == 1:
        return False

    visited[s] = 1
    ans  = False

    for i in range(N):
        if i == s:
            continue

        a = nodes[s][0]
        b = nodes[s][1]
        c = nodes[i][0]
        d = nodes[i][1]

        if (c<a and a<d) or (c<b and b<d):
            ans = ans or dfs(i ,e)

    return ans

nodes = []
N = 0
M = int(input())

for k in range(M):
    con , u , v = tuple(int(i) for i in input().split())

    if con == 1:
        V = [u,v]
        nodes.append(V)
        N += 1

    else:
         u -= 1
         v -= 1
         reset()
         if dfs(u ,v):
             print("YES")
         else:
             print("NO")

from collections import deque

def solve():
    t = int(input().rstrip())
    nodes = []
    graph = {}
    for _ in range(t):
        k, x, y = list(map(int, input().rstrip().split()))
        if k == 1:
            nodes.append((x,y)) 
            if (x,y) not in graph:
                graph[(x,y)] = []
            for a, b in graph:
                if a < x < b or a < y < b:
                    graph[(x,y)].append((a,b))
                if x < a < y or x < b < y:
                    graph[(a,b)].append((x,y))
        elif k == 2:
            a, b = nodes[x-1]
            c, d = nodes[y-1]
            stack = deque()
            stack.append((a,b))
            seen = set()
            while len(stack) > 0 and (c, d) not in seen:
                cur, dest = stack.pop()
                seen.add((cur, dest))
                for m, n in graph[(cur, dest)]:
                    if (m, n) not in seen:
                        stack.append((m, n))
            if (c, d) in seen:
                print('YES')
            else:
                print('NO')


def __starting_point():
    solve()

__starting_point()

from collections import deque
from sys import stdin

N = int(stdin.readline().rstrip())
nodes = []
adj_list = []
for n in range(0, N):
    type, a, b = map(int, stdin.readline().rstrip().split())
    if type == 1:
        adj_list.append([])
        for index in range(0, len(nodes)):
            (c, d) = nodes[index]
            if c < a < d or c < b < d:
                adj_list[len(nodes)].append(index)
            if a < c < b or a < d < b:
                adj_list[index].append(len(nodes))
        nodes.append((a, b))
    else:
        queue = deque()
        visited = [False] * len(nodes)
        a -= 1
        b -= 1
        queue.append(a)
        path = False
        while queue:
            c = queue.popleft()
            if c == b:
                path = True
                break
            else:
                for d in adj_list[c]:
                    if not visited[d]:
                        queue.append(d)
                        visited[d] = True
        if path:
            print('YES')
        else:
            print('NO')

def in_interval(w, x, y, z):
	if (w > y and w < z) or (x > y and x < z):
		return True
	else:
		return False

def step_through(a, b, c, d, temp):
	x = None
	for interval in temp:
		e = int(interval[0])
		f = int(interval[1])
		if in_interval(a,b,c,d):
			return True
		elif in_interval(a,b,e,f):
			x = interval
			temp.remove(interval)
			if step_through(e,f,c,d,temp):
				return True
	if(x != None):
		temp.append(x)
	return False

n = int(input())
set_of_intervals = []
for i in range (n):
	line = input().split()

	if line[0] == "1":
		set_of_intervals.append([line[1], line[2]])
	else:
		a = int(set_of_intervals[int(line[1]) - 1][0])
		b = int(set_of_intervals[int(line[1]) - 1][1])
		c = int(set_of_intervals[int(line[2]) - 1][0])
		d = int(set_of_intervals[int(line[2]) - 1][1])

		temp = set_of_intervals[:]
		temp.pop(int(line[1]) - 1)
		if(step_through(a,b,c,d, temp)):
			print ("YES")
		else:
			print("NO")


def input_tuple(f):
    return tuple(map(f, input().rstrip().split()))

def make_edge(i1, i2, adj_list):
    i, a, b = i1
    j, c, d = i2
    if c < a < d or c < b < d:
        adj_list[i].append(j)

def dfs(curr, dest, seen, intervals):
    i, a, b = curr
    if i == dest:
        return True
    seen.add(i)
    for j, c, d in intervals:
        if j in seen:
            continue
        if c < a < d or c < b < d:
            if dfs((j, c, d), dest, seen, intervals):
                return True
    return False

def __starting_point():
    intervals = []
    num_queries = int(input().rstrip())
    i = 1
    for _ in range(num_queries):
        t, a, b = input_tuple(int)
        if t == 1:
            intervals.append((i, a, b))
            i += 1
        elif t == 2:
            if dfs(intervals[a-1], b, set(), intervals):
                print('YES')
            else:
                print('NO')

__starting_point()

path = []
n = int(input())
for it in range(0, n):
	data = list(map(int, input().split(' ')))
	if data[0] == 1:
		path.append(data[1:])
	else:
		vis = [False] * (len(path) + 1)
		que = [data[1] - 1]
		while len(que):
			p = que[0]
			del que[0]
			for i, v in enumerate(path):
				if (v[0] < path[p][0] < v[1] or v[0] < path[p][1] < v[1]) and not vis[i]:
					vis[i] = True
					que.append(i)
		print('YES' if vis[data[2] -1] else 'NO')


# intervals and visited intervals have the same key
# which is the order in which intervals were queried

counter = 1
queries = int(input())
visited_intervals = [0] * (queries + 1)

intervals = {}

def get_interval():
    return tuple(map(int, input().split()))

def reset_search_data():
    nonlocal queries
    nonlocal visited_intervals
    del visited_intervals
    visited_intervals = [0] * queries

def solve():

    nonlocal counter
    nonlocal visited_intervals

    for _ in range (queries):
        query = get_interval()
        if query[0] == 1:
           intervals[counter] = query
           counter += 1
        elif query[0] == 2:
            q = []
            q.append(query[1])
            # start new search
            reset_search_data()
            while len(q) > 0:
                q_interval = q.pop(0)
                for index in intervals:
                    c = intervals[index][1]
                    d = intervals[index][2]
                    a = intervals[q_interval][1]
                    b = intervals[q_interval][2]
                    if c < a < d or c < b < d:
                        if visited_intervals[index] == 0:
                            #print ("TRUE", c, a , d, " ", c ,b ,d )
                            #print("marking ", index)
                            visited_intervals[index] = 1
                            #print ("visited", index)
                            q.append(index)
            if visited_intervals[query[2]] == 1:
                print ("YES")
            else:
                print ("NO")
solve()

def graphAdd(u, v, G):
	for a, b in G:
		if (a<u and u<b) or (a<v and v<b):
			connect(G, u, v, a, b)
		if (u<a and a<v) or (u<b and b<v):
			connect(G, a, b, u, v)

def connect(G, u, v, w, x):
	G[(u, v)][(w, x)] = 1

def queueSort(G, l, u, v):
	start = l[u-1]
	visited = dict()
	visited[start] = 1
	end = l[v-1]

	q = [start]

	while q != []:
		cur = q.pop(0)
		for a, b in G[cur]:
			if ((a, b) == end):
				return "YES"
			if ((a,b) not in visited):
				visited[(a,b)] = 1
				q.append((a,b))
	return "NO"

numTest = int(input())

G = dict()
l = list()

while(numTest>0):

	inputList= list(map(int, input().split()))
	a = inputList[0]
	b = inputList[1]
	c = inputList[2]

	if a == 1:
		G[(b, c)] = {}
		graphAdd(b, c, G)
		l.append((b,c))
	else:
		print(queueSort(G, l, b, c))

	numTest -= 1

"""
Solution to the 320B problem on CodeForces.

# pylint: disable = C0325
# pylint: disable = W0611
"""

from collections import deque

def filter_intervals(intv, input_list):
    """
    Filters the list for all the intervals that are valid.
    """
    return ((x, y) for x, y in input_list if (int(intv[0]) > int(x) and int(intv[0]) < int(y)) or \
                                             (int(intv[1]) > int(x) and int(intv[1]) < int(y)))

def interval_search(intv, target, input_list):
    """
    Finds if a path exists from one interval to another.
    """
    visited = set()
    d = deque()
    d.append(intv)
    while d:
        intv = d.pop()
        if intv == target:
            return True
        if intv not in visited:
            visited.add(intv)
            for interval in filter_intervals(intv, input_list):
                if interval not in visited:
                    d.append(interval)
    return False

def main():
    """
    Docstring or main.
    """
    num_inputs = int(input())
    interval_list = []
    for _ in range(num_inputs):
        input_type, beg, end = input().split()
        beg = int(beg)
        end = int(end)
        if int(input_type) == 1:
            interval_list.append((beg, end))
        else:
            if interval_search(interval_list[beg-1], interval_list[end-1], interval_list):
                print("YES")
            else:
                print("NO")

def __starting_point():
    main()

__starting_point()