← Home
```go
package main

import (
	"bufio"
	"container/heap"
	"fmt"
	"os"
	"sort"
)

type Item struct {
	r  int
	id int
}

type MinHeap []Item

func (h MinHeap) Len() int           { return len(h) }
func (h MinHeap) Less(i, j int) bool { return h[i].r < h[j].r }
func (h MinHeap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }

func (h *MinHeap) Push(x interface{}) {
	*h = append(*h, x.(Item))
}

func (h *MinHeap) Pop() interface{} {
	old := *h
	n := len(old)
	x := old[n-1]
	*h = old[0 : n-1]
	return x
}

type DSU struct {
	parent []int
	size   []int
	groups int
}

func NewDSU(n int) *DSU {
	parent := make([]int, n)
	size := make([]int, n)
	for i := range parent {
		parent[i] = i
		size[i] = 1
	}
	return &DSU{parent: parent, size: size, groups: n}
}

func (d *DSU) Find(i int) int {
	if d.parent[i] == i {
		return i
	}
	d.parent[i] = d.Find(d.parent[i])
	return d.parent[i]
}

func (d *DSU) Union(i, j int) {
	rootI := d.Find(i)
	rootJ := d.Find(j)
	if rootI != rootJ {
		if d.size[rootI] < d.size[rootJ] {
			rootI, rootJ = rootJ, rootI
		}
		d.parent[rootJ] = rootI
		d.size[rootI] += d.size[rootJ]
		d.groups--
	}
}

type Segment struct {
	id int
	c  int
	l  int
	r  int
}

var scanner *bufio.Scanner

func init() {
	scanner = bufio.NewScanner(os.Stdin)
	scanner.Split(bufio.ScanWords)
	scanner.Buffer(make([]byte, 1024*1024), 1024*1024*10)
}

func readInt() int {
	scanner.Scan()
	b := scanner.Bytes()
	res := 0
	for _, v := range b {
		res = res*10 + int(v-'0')
	}
	return res
}

func main() {
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()

	if !scanner.Scan() {
		return
	}
	b := scanner.Bytes()
	t := 0
	for _, v := range b {
		t = t*10 + int(v-'0')
	}

	for i := 0; i < t; i++ {
		n := readInt()
		segments := make([]Segment, n)
		for j := 0; j < n; j++ {
			segments[j] = Segment{
				id: j,
				c:  readInt(),
				l:  readInt(),
				r:  readInt(),
			}
		}

		sort.Slice(segments, func(a, b int) bool {
			if segments[a].l != segments[b].l {
				return segments[a].l < segments[b].l
			}
			return segments[a].r < segments[b].r
		})

		dsu := NewDSU(n)
		act := [2]*MinHeap{&MinHeap{}, &MinHeap{}}
		heap.Init(act[0])
		heap.Init(act[1])

		for j := 0; j < n; j++ {
			s := segments[j]

			for act[0].Len() > 0 && (*act[0])[0].r < s.l {
				heap.Pop(act[0])
			}
			for act[1].Len() > 0 && (*act[1])[0].r < s.l {
				heap.Pop(act[1])
			}

			other := 1 - s.c
			if act[other].Len() > 0 {
				maxR := -1
				for act[other].Len() > 0 {
					item := heap.Pop(act[other]).(Item)
					if item.r > maxR {
						maxR = item.r
					}
					dsu.Union(s.id, item.id)
				}
				heap.Push(act[other], Item{r: maxR, id: s.id})
			}

			heap.Push(act[s.c], Item{r: s.r, id: s.id})
		}

		fmt.Fprintln(out, dsu.groups)
	}
}
```