← Home
```go
package main

import (
	"bufio"
	"os"
)

type Point struct {
	Y, X int64
}

type Node struct {
	P        Point
	Priority uint32
	Left     *Node
	Right    *Node
}

var seed uint32 = 123456789

func fastRand() uint32 {
	seed ^= seed << 13
	seed ^= seed >> 17
	seed ^= seed << 5
	return seed
}

func rightRotate(y *Node) *Node {
	x := y.Left
	y.Left = x.Right
	x.Right = y
	return x
}

func leftRotate(x *Node) *Node {
	y := x.Right
	x.Right = y.Left
	y.Left = x
	return y
}

func insert(root *Node, p Point) *Node {
	if root == nil {
		return &Node{P: p, Priority: fastRand()}
	}
	if p.Y < root.P.Y {
		root.Left = insert(root.Left, p)
		if root.Left.Priority > root.Priority {
			root = rightRotate(root)
		}
	} else if p.Y > root.P.Y {
		root.Right = insert(root.Right, p)
		if root.Right.Priority > root.Priority {
			root = leftRotate(root)
		}
	}
	return root
}

func deleteNode(root *Node, y int64) *Node {
	if root == nil {
		return nil
	}
	if y < root.P.Y {
		root.Left = deleteNode(root.Left, y)
	} else if y > root.P.Y {
		root.Right = deleteNode(root.Right, y)
	} else {
		if root.Left == nil {
			return root.Right
		}
		if root.Right == nil {
			return root.Left
		}
		if root.Left.Priority > root.Right.Priority {
			root = rightRotate(root)
			root.Right = deleteNode(root.Right, y)
		} else {
			root = leftRotate(root)
			root.Left = deleteNode(root.Left, y)
		}
	}
	return root
}

func findMaxYLeq(root *Node, y int64) *Node {
	var res *Node
	for root != nil {
		if root.P.Y <= y {
			res = root
			root = root.Right
		} else {
			root = root.Left
		}
	}
	return res
}

func findMinYGt(root *Node, y int64) *Node {
	var res *Node
	for root != nil {
		if root.P.Y > y {
			res = root
			root = root.Left
		} else {
			root = root.Right
		}
	}
	return res
}

func isBelowOrOn(A, B, C Point) bool {
	return (B.X-A.X)*(C.Y-A.Y) <= (C.X-A.X)*(B.Y-A.Y)
}

func addPoint(root *Node, p Point) *Node {
	existing := findMaxYLeq(root, p.Y)
	if existing != nil && existing.P.Y == p.Y {
		if p.X <= existing.P.X {
			return root
		}
		root = deleteNode(root, p.Y)
	}

	A := findMaxYLeq(root, p.Y-1)
	B := findMinYGt(root, p.Y)
	if B != nil {
		if isBelowOrOn(A.P, p, B.P) {
			return root
		}
	} else {
		if p.X <= A.P.X {
			return root
		}
	}

	root = insert(root, p)

	for {
		currA := findMaxYLeq(root, p.Y-1)
		if currA == nil || currA.P.Y == 0 {
			break
		}
		prevA := findMaxYLeq(root, currA.P.Y-1)
		if isBelowOrOn(prevA.P, currA.P, p) {
			root = deleteNode(root, currA.P.Y)
		} else {
			break
		}
	}

	for {
		currB := findMinYGt(root, p.Y)
		if currB == nil {
			break
		}
		nextB := findMinYGt(root, currB.P.Y)
		if nextB != nil {
			if isBelowOrOn(p, currB.P, nextB.P) {
				root = deleteNode(root, currB.P.Y)
			} else {
				break
			}
		} else {
			if currB.P.X <= p.X {
				root = deleteNode(root, currB.P.Y)
			} else {
				break
			}
		}
	}

	return root
}

func query(root *Node, t, h, m int64) bool {
	Yq := m / t
	A := findMaxYLeq(root, Yq)
	B := findMinYGt(root, Yq)
	if B == nil {
		return t*A.P.X >= h
	}
	lhs := t*A.P.X*(B.P.Y-A.P.Y) + (B.P.X-A.P.X)*(m-t*A.P.Y)
	rhs := h * (B.P.Y - A.P.Y)
	return lhs >= rhs
}

func main() {
	in, _ := os.ReadFile("/dev/stdin")
	pos := 0
	next := func() int64 {
		for pos < len(in) && in[pos] <= ' ' {
			pos++
		}
		if pos >= len(in) {
			return 0
		}
		res := int64(0)
		for pos < len(in) && in[pos] > ' ' {
			res = res*10 + int64(in[pos]-'0')
			pos++
		}
		return res
	}

	q := next()
	if q == 0 {
		return
	}
	m := next()

	var root *Node
	root = addPoint(root, Point{0, 0})

	j := int64(0)
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()

	for i := int64(1); i <= q; i++ {
		k := next()
		a := next()
		b := next()

		if k == 1 {
			x := (a+j)%1000000 + 1
			y := (b+j)%1000000 + 1
			root = addPoint(root, Point{Y: y, X: x})
		} else if k == 2 {
			t := (a+j)%1000000 + 1
			h := (b+j)%1000000 + 1
			if query(root, t, h, m) {
				out.WriteString("YES\n")
				j = i
			} else {
				out.WriteString("NO\n")
			}
		}
	}
}
```