← Home
```go
package main

import (
	"bufio"
	"fmt"
	"math/bits"
	"os"
	"strings"
)

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	scanner.Split(bufio.ScanLines)

	scanner.Scan()
	line := scanner.Text()
	var n, m int
	fmt.Sscanf(line, "%d %d", &n, &m)

	events := make([]struct {
		typ  int
		name string
	}, n)

	nameToIdx := make(map[string]int)

	for i := 0; i < n; i++ {
		scanner.Scan()
		line = strings.TrimSpace(scanner.Text())
		if line[0] == '1' {
			events[i].typ = 1
		} else {
			events[i].typ = 2
			parts := strings.Split(line, " ")
			name := parts[1]
			events[i].name = name
			if _, ok := nameToIdx[name]; !ok {
				nameToIdx[name] = len(nameToIdx)
			}
		}
	}

	friendSegs := make([]map[int]bool, m)
	for i := range friendSegs {
		friendSegs[i] = make(map[int]bool)
	}

	curSeg := -1
	for _, ev := range events {
		if ev.typ == 1 {
			curSeg++
		} else {
			idx := nameToIdx[ev.name]
			friendSegs[idx][curSeg] = true
		}
	}

	conflict := make([]uint64, m)
	for i := 0; i < m; i++ {
		for j := i + 1; j < m; j++ {
			intersect := false
			if len(friendSegs[i]) > len(friendSegs[j]) {
				for seg := range friendSegs[j] {
					if friendSegs[i][seg] {
						intersect = true
						break
					}
				}
			} else {
				for seg := range friendSegs[i] {
					if friendSegs[j][seg] {
						intersect = true
						break
					}
				}
			}
			if intersect {
				conflict[i] |= 1 << uint(j)
				conflict[j] |= 1 << uint(i)
			}
		}
	}

	m1 := m / 2
	m2 := m - m1
	sizeA := 1 << m1
	dp := make([]int, sizeA)

	for mask := 1; mask < sizeA; mask++ {
		lsb := mask & -mask
		v := bits.TrailingZeros(uint(lsb))
		maskWithoutV := mask ^ lsb
		best := dp[maskWithoutV]
		neighbors := int(conflict[v] & uint64(mask))
		maskWithoutNeighbors := maskWithoutV & ^neighbors
		cand := 1 + dp[maskWithoutNeighbors]
		if cand > best {
			best = cand
		}
		dp[mask] = best
	}

	fullA := sizeA - 1
	ans := 0
	sizeB := 1 << m2

	for maskB := 0; maskB < sizeB; maskB++ {
		valid := true
		forbiddenA := 0
		temp := maskB
		for temp > 0 {
			lsb := temp & -temp
			i := bits.TrailingZeros(uint(lsb))
			v := m1 + i
			conflictB := int((conflict[v] >> uint(m1)) & uint64(sizeB-1))
			if conflictB&maskB != 0 {
				valid = false
				break
			}
			forbiddenA |= int(conflict[v] & uint64(fullA))
			temp -= lsb
		}
		if !valid {
			continue
		}
		allowedA := fullA & ^forbiddenA
		total := bits.OnesCount(uint(maskB)) + dp[allowedA]
		if total > ans {
			ans = total
		}
	}

	fmt.Println(ans)
}
```