```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")
}
}
}
}
```