You are given $n$ colored segments on the number line. Each segment is either colored red or blue. The $i$-th segment can be represented by a tuple $(c_i, l_i, r_i)$. The segment contains all the points in the range $[l_i, r_i]$, inclusive, and its color denoted by $c_i$:

if $c_i = 0$, it is a red segment;

if $c_i = 1$, it is a blue segment.

We say that two segments of different colors are connected, if they share at least one common point. Two segments belong to the same group, if they are either connected directly, or through a sequence of directly connected segments. Find the number of groups of segments.


-----Input-----

Each test contains multiple test cases. The first line contains the number of test cases $t$ ($1 \le t \le 10^5$). Description of the test cases follows.

The first line of each test case contains a single integer $n$ ($1 \leq n \leq 10^5$) — the number of segments.

Each of the next $n$ lines contains three integers $c_i, l_i, r_i$ ($0 \leq c_i \leq 1, 0 \leq l_i \leq r_i \leq 10^9$), describing the $i$-th segment.

It is guaranteed that the sum of $n$ over all test cases does not exceed $10^5$.


-----Output-----

For each test case, print a single integer $k$, the number of groups of segments.


-----Examples-----

Input
2
5
0 0 5
1 2 12
0 4 7
1 9 16
0 13 19
3
1 0 1
1 1 2
0 3 4
Output
2
3


-----Note-----

In the first example there are $5$ segments. The segments $1$ and $2$ are connected, because they are of different colors and share a point. Also, the segments $2$ and $3$ are connected, and so are segments $4$ and $5$. Thus, there are two groups: one containing segments $\{1, 2, 3\}$, and the other one containing segments $\{4, 5\}$.

Source: codeforces | Difficulty: HARD
Tags: Graph algorithms

Graph traversal

Sorting

Greedy algorithms

Spanning trees

Data structures


Solutions:
from sys import stdin

def solve_case():
	n = int(stdin.readline())
	segs = [tuple(map(int, stdin.readline().split())) + (i,) for i in range(n)]
	segs.sort(key=lambda x: x[1])
	par = [-1] * n
	cnt_comp = n

	def find_set(u):
		p = u
		while par[p] >= 0:
			p = par[p]
		while u != p:
			t = par[u]
			par[u] = p
			u = t
		return p

	def join(u, v):
		nonlocal cnt_comp
		nonlocal par
		u = find_set(u)
		v = find_set(v)
		if u == v:
			return
		if -par[u] < -par[v]:
			(u, v) = (v, u)
		par[u] += par[v]
		par[v] = u
		cnt_comp -= 1
	hp = [[], []]
	for (col, l, r, id) in segs:
		for elm in hp[1 - col]:
			if elm[0] < l:
				continue
			join(elm[1], id)
		if len(hp[1 - col]):
			hp[1 - col] = [max(hp[1 - col])]
		hp[col].append((r, id))
	return cnt_comp
for testcase in range(int(stdin.readline())):
	print(solve_case())


from collections import deque
tc = int(input())
for t in range(tc):
	n = int(input())
	red = []
	blue = []
	for j in range(n):
		(c, s, f) = map(int, input().split())
		if c == 0:
			red.append([s, f, 'r'])
		else:
			blue.append([s, f, 'b'])
	red.sort(reverse=True)
	blue.sort(reverse=True)
	stck = deque()
	coun = 0
	while 1:
		if len(stck) == 0 and blue and red:
			coun = coun + 1
			if red[-1][1] <= blue[-1][1]:
				stck.append(red.pop())
			else:
				stck.append(blue.pop())
		elif len(stck) == 0 and (len(blue) == 0 or len(red) == 0):
			if len(blue) == 0:
				coun = coun + len(red)
				break
			else:
				coun = coun + len(blue)
				break
		q = stck.popleft()
		if q[-1] == 'r':
			while blue and blue[-1][0] <= q[1]:
				if blue[-1][1] < q[0]:
					blue.pop()
					coun += 1
					continue
				stck.append(blue.pop())
		else:
			while red and red[-1][0] <= q[1]:
				if red[-1][1] < q[0]:
					red.pop()
					coun += 1
					continue
				stck.append(red.pop())
	print(coun)


t = int(input())
for _ in range(t):
	n = int(input())
	ends = []
	for i in range(n):
		(c, l, r) = map(int, input().split())
		ends.append((l, 0, c, i))
		ends.append((r, 1, c, i))
	ends.sort()
	groups = n
	wait = [set(), set()]
	combined = [0, 0]
	totals = [0, 0]
	for (bound, is_closed, color, i) in ends:
		if not is_closed:
			if totals[1 - color] == 0:
				wait[color].add(i)
			elif len(wait[1 - color]) > 0:
				L = len(wait[1 - color])
				groups -= combined[1 - color] > 0
				combined[1 - color] += L
				wait[1 - color] = set()
				combined[color] += 1
				groups -= L
			else:
				combined[color] += 1
				groups -= 1
			totals[color] += 1
		else:
			if i in wait[color]:
				wait[color].remove(i)
			else:
				combined[color] -= 1
			totals[color] -= 1
	print(groups)