import sys
import bisect
# ------------------------------------------------------------
# upper convex hull of points (y, x) (y = mana per second,
# x = damage per second)
# ------------------------------------------------------------
class UpperHull:
"""maintains the upper convex hull of points (y, x) with y increasing"""
def __init__(self):
# start with the origin
self.ys = [0] # list of y coordinates, strictly increasing
self.xs = [0] # corresponding x coordinates
# -----------------------------------------------------------------
# test whether the middle point (i) of three consecutive points
# (i-1, i, i+1) is redundant for the upper hull
# -----------------------------------------------------------------
@staticmethod
def _bad(x1, y1, x2, y2, x3, y3):
# slope12 = (x2-x1)/(y2-y1)
# slope23 = (x3-x2)/(y3-y2)
# point 2 is bad iff slope12 <= slope23
return (x2 - x1) * (y3 - y2) <= (x3 - x2) * (y2 - y1)
# -----------------------------------------------------------------
# insert a new point (y, x)
# -----------------------------------------------------------------
def add(self, y, x):
# find position
pos = bisect.bisect_left(self.ys, y)
if pos < len(self.ys) and self.ys[pos] == y:
# same y already present
if self.xs[pos] >= x:
return # new point is not better
# replace with larger x
self.xs[pos] = x
# after raising x the hull may need fixing
else:
self.ys.insert(pos, y)
self.xs.insert(pos, x)
# fix the hull to the left of the inserted/changed point
i = max(pos - 2, 0)
while i + 2 < len(self.ys):
if self._bad(self.xs[i], self.ys[i],
self.xs[i + 1], self.ys[i + 1],
self.xs[i + 2], self.ys[i + 2]):
# remove middle point i+1
del self.ys[i + 1]
del self.xs[i + 1]
# stay at the same i (new triple may also be bad)
if i > 0:
i -= 1
else:
i += 1
# -----------------------------------------------------------------
# query maximal x for a given maximal y (average mana) M
# -----------------------------------------------------------------
def max_x_at_mana(self, M):
# binary search: last index with y <= M
idx = bisect.bisect_right(self.ys, M) - 1
if idx == len(self.ys) - 1: # M beyond the last vertex
return float(self.xs[-1])
if self.ys[idx] == M:
return float(self.xs[idx])
# linear interpolation between idx and idx+1
y1, x1 = self.ys[idx], self.xs[idx]
y2, x2 = self.ys[idx + 1], self.xs[idx + 1]
# avoid division by zero – y2 > y1 because y are strictly increasing
return x1 + (x2 - x1) * (M - y1) / (y2 - y1)
# ------------------------------------------------------------
def solve() -> None:
data = sys.stdin.read().strip().split()
if not data:
return
it = iter(data)
q = int(next(it))
m = int(next(it))
hull = UpperHull()
j = 0 # index of last positively answered type 2 query
out_lines = []
for idx in range(1, q + 1):
k = int(next(it))
a = int(next(it))
b = int(next(it))
if k == 1: # learn a spell
x = (a + j) % 1_000_000 + 1
y = (b + j) % 1_000_000 + 1
hull.add(y, x)
else: # fight a monster
t = (a + j) % 1_000_000 + 1
h = (b + j) % 1_000_000 + 1
M = m / t # maximal average mana per second
best_damage_per_sec = hull.max_x_at_mana(M)
max_total_damage = best_damage_per_sec * t
if max_total_damage + 1e-9 >= h:
out_lines.append("YES")
j = idx # this query answered YES
else:
out_lines.append("NO")
# j stays unchanged
sys.stdout.write("\n".join(out_lines))
if __name__ == "__main__":
solve()