package main
import (
"bufio"
"io"
"os"
"sort"
"strconv"
)
const negInf int64 = -1 << 60
type BIT struct {
n int
bit []int64
}
func NewBIT(n int) *BIT {
return &BIT{n: n, bit: make([]int64, n+2)}
}
func (b *BIT) Add(i int, v int64) {
for i <= b.n {
b.bit[i] += v
i += i & -i
}
}
func (b *BIT) Sum(i int) int64 {
var res int64
for i > 0 {
res += b.bit[i]
i -= i & -i
}
return res
}
type Seg struct {
mx []int64
lz []int64
}
func NewSeg(n int) *Seg {
sz := 4*n + 5
mx := make([]int64, sz)
lz := make([]int64, sz)
for i := range mx {
mx[i] = negInf
}
return &Seg{mx: mx, lz: lz}
}
func (s *Seg) apply(p int, v int64) {
s.mx[p] += v
s.lz[p] += v
}
func (s *Seg) push(p int) {
if s.lz[p] != 0 {
v := s.lz[p]
s.apply(p<<1, v)
s.apply(p<<1|1, v)
s.lz[p] = 0
}
}
func (s *Seg) Add(p, l, r, ql, qr int, v int64) {
if ql > r || qr < l {
return
}
if ql <= l && r <= qr {
s.apply(p, v)
return
}
s.push(p)
m := (l + r) >> 1
if ql <= m {
s.Add(p<<1, l, m, ql, qr, v)
}
if qr > m {
s.Add(p<<1|1, m+1, r, ql, qr, v)
}
if s.mx[p<<1] > s.mx[p<<1|1] {
s.mx[p] = s.mx[p<<1]
} else {
s.mx[p] = s.mx[p<<1|1]
}
}
func (s *Seg) Set(p, l, r, idx int, v int64) {
if l == r {
s.mx[p] = v
s.lz[p] = 0
return
}
s.push(p)
m := (l + r) >> 1
if idx <= m {
s.Set(p<<1, l, m, idx, v)
} else {
s.Set(p<<1|1, m+1, r, idx, v)
}
if s.mx[p<<1] > s.mx[p<<1|1] {
s.mx[p] = s.mx[p<<1]
} else {
s.mx[p] = s.mx[p<<1|1]
}
}
func (s *Seg) Query(p, l, r, ql, qr int) int64 {
if ql > r || qr < l {
return negInf
}
if ql <= l && r <= qr {
return s.mx[p]
}
s.push(p)
m := (l + r) >> 1
left := s.Query(p<<1, l, m, ql, qr)
right := s.Query(p<<1|1, m+1, r, ql, qr)
if left > right {
return left
}
return right
}
func main() {
data, _ := io.ReadAll(os.Stdin)
ptr := 0
nextInt := func() int {
for ptr < len(data) && (data[ptr] < '0' || data[ptr] > '9') {
ptr++
}
v := 0
for ptr < len(data) && data[ptr] >= '0' && data[ptr] <= '9' {
v = v*10 + int(data[ptr]-'0')
ptr++
}
return v
}
n := nextInt()
L := make([]int, n)
R := make([]int, n)
C := make([]int, n)
coords := make([]int, 0, 2*n)
for i := 0; i < n; i++ {
l := nextInt()
r := nextInt()
t := nextInt() - 1
L[i], R[i], C[i] = l, r, t
coords = append(coords, l, r)
}
sort.Ints(coords)
vals := coords[:0]
for _, x := range coords {
if len(vals) == 0 || vals[len(vals)-1] != x {
vals = append(vals, x)
}
}
m := len(vals)
start0 := make([]bool, m+1)
start1 := make([]bool, m+1)
heads0 := make([]int, m+1)
heads1 := make([]int, m+1)
for i := 0; i <= m; i++ {
heads0[i] = -1
heads1[i] = -1
}
leftIdx := make([]int, n)
nextEnd := make([]int, n)
for i := 0; i < n; i++ {
li := sort.SearchInts(vals, L[i]) + 1
ri := sort.SearchInts(vals, R[i]) + 1
leftIdx[i] = li
if C[i] == 0 {
start0[li] = true
nextEnd[i] = heads0[ri]
heads0[ri] = i
} else {
start1[li] = true
nextEnd[i] = heads1[ri]
heads1[ri] = i
}
}
seg0 := NewSeg(m)
seg1 := NewSeg(m)
bit0 := NewBIT(m)
bit1 := NewBIT(m)
var pref0, pref1 int64
var total0, total1 int64
var maxL0, maxL1 int
for i := 1; i <= m; i++ {
for e := heads0[i]; e != -1; e = nextEnd[e] {
l := leftIdx[e]
total0++
if l > maxL0 {
maxL0 = l
}
if l < m {
seg0.Add(1, 1, m, l+1, m, -1)
bit0.Add(l+1, -1)
}
}
for e := heads1[i]; e != -1; e = nextEnd[e] {
l := leftIdx[e]
total1++
if l > maxL1 {
maxL1 = l
}
if l < m {
seg1.Add(1, 1, m, l+1, m, -1)
bit1.Add(l+1, -1)
}
}
if start0[i] {
seg0.Set(1, 1, m, i, pref1+bit0.Sum(i))
}
if start1[i] {
seg1.Set(1, 1, m, i, pref0+bit1.Sum(i))
}
dp0 := negInf
dp1 := negInf
if total0 > 0 && maxL0 > 0 {
best := seg0.Query(1, 1, m, 1, maxL0)
if best > negInf/2 {
dp0 = total0 + best
}
}
if total1 > 0 && maxL1 > 0 {
best := seg1.Query(1, 1, m, 1, maxL1)
if best > negInf/2 {
dp1 = total1 + best
}
}
if dp0 > pref0 {
pref0 = dp0
}
if dp1 > pref1 {
pref1 = dp1
}
}
ans := pref0
if pref1 > ans {
ans = pref1
}
out := bufio.NewWriterSize(os.Stdout, 1<<20)
out.WriteString(strconv.FormatInt(ans, 10))
out.Flush()
}