Climbing the Tree (Codeforces 1810D)
Tags: Math, binary search

The snails are climbing a tree. The tree height is $$$h$$$ meters, and snails start at position $$$0$$$.Each snail has two attributes $$$a$$$ and $$$b$$$ ($$$a > b$$$). Starting from the $$$1$$$-st day, one snail climbs the tree like this: during the daylight hours of the day, he climbs up $$$a$$$ meters; during the night, the snail rests, and he slides down $$$b$$$ meters. If on the $$$n$$$-th day, the snail reaches position $$$h$$$ for the first time (that is, the top of the tree), he will finish climbing, and we say that the snail spends $$$n$$$ days climbing the tree. Note that on the last day of climbing, the snail doesn't necessarily climb up $$$a$$$ meters, in case his distance to the top is smaller than $$$a$$$.Unfortunately, you don't know the exact tree height $$$h$$$ at first, but you know that $$$h$$$ is a positive integer. There are $$$q$$$ events of two kinds.  Event of type $$$1$$$: a snail with attributes $$$a$$$, $$$b$$$ comes and claims that he spent $$$n$$$ days climbing the tree. If this message contradicts previously adopted information (i. e. there is no tree for which all previously adopted statements and this one are true), ignore it. Otherwise, adopt it. Event of type $$$2$$$: a snail with attributes $$$a$$$, $$$b$$$ comes and asks you how many days he will spend if he climbs the tree. You can only give the answer based on the information you have adopted so far. If you cannot determine the answer precisely, report that. You need to deal with all the events in order.

Input: Each test contains multiple test cases. The first line contains a single integer $$$t$$$ ($$$1 \le t \le 10^4$$$) — the number of test cases. Then follows their description.The first line of each test case contains one integer $$$q$$$ ($$$1\le q \le 2\cdot 10^5$$$) — the number of events.For the following $$$q$$$ lines, the first integer of each line is either $$$1$$$ or $$$2$$$, denoting the event type.If the event type is $$$1$$$, then three integers $$$a$$$, $$$b$$$, and $$$n$$$ ($$$1\le a,b,n \le 10^9$$$, $$$a>b$$$) follow.If the event type is $$$2$$$, then two integers $$$a$$$ and $$$b$$$ ($$$1\le a,b \le 10^9$$$, $$$a>b$$$) follow.It is guaranteed that the sum of $$$q$$$ over all test cases does not exceed $$$2\cdot 10^5$$$.

Output: For each test case, output $$$q$$$ integers in one line, one for each event, in order. Specifically,   for each event of type $$$1$$$, if you adopt the message, output $$$1$$$; if you ignore it, output $$$0$$$;  for each event of type $$$2$$$, output an integer denoting the number of days that the snail will spend. If you cannot determine it, output $$$-1$$$. 

Note: In the first test case, we can determine $$$h=7$$$ through the first message, so we know the second snail and the third snail need to spend $$$2$$$ and $$$5$$$ days respectively to reach the top.Let's show how the second snail climbs:  During the daylight hours of the $$$1$$$st day: climbs up $$$4$$$ meters, now at position $$$4$$$.  During the night of the $$$1$$$st day: slides down $$$1$$$ meters, now at position $$$3$$$.  During the daylight hours of the $$$2$$$nd day: climbs up $$$4$$$ meters, now at position $$$7$$$ (reaches the top). In the third test case, the second snail's message contradicts the first snail's, because the second snail says he spent $$$3$$$ days, and he can climb at most $$$1+1+2=4$$$ meters in the first $$$3$$$ days. However, the first snail only needs $$$1$$$ day to climb $$$4$$$ meters.

Sample Inputs:
5
3
1 3 2 5
2 4 1
2 3 2
3
1 6 5 1
2 3 1
2 6 2
3
1 4 2 2
1 2 1 3
2 10 2
9
1 7 3 6
1 2 1 8
2 5 1
1 10 9 7
1 8 1 2
1 10 5 8
1 10 7 7
2 7 4
1 9 4 2
9
1 2 1 6
1 8 5 6
1 4 2 7
2 9 1
1 5 1 4
1 5 2 7
1 7 1 9
1 9 1 4
2 10 8

Sample Outputs:
1 2 5
1 -1 1
1 0 1
1 0 -1 0 0 0 1 8 0
1 0 0 1 0 0 0 0 1

Solution (Python):
import sys

def process_events(num_events):
    (L, H) = (0, 9 ** 20)
    for _ in range(num_events):
        event = list(map(int, sys.stdin.readline().split()))
        if event[0] == 1:
            (a, b, n) = event[1:]
            v = a + 1 + (n - 2) * (a - b) if n > 1 else 1
            w = a + (n - 1) * (a - b) if n > 1 else a
            if L != 0:
                if v > H or w < L:
                    print(0)
                    continue
                (L, H) = (max(L, v), min(H, w))
            else:
                (L, H) = (v, w)
            print(1)
        else:
            (a, b) = event[1:]
            v = 2 + (L - a - 1) // (a - b) if L > a else 1
            w = 2 + (H - a - 1) // (a - b) if H > a else 1
            print(-1 if v != w else v)

def main():
    t = int(sys.stdin.readline())
    for _ in range(t):
        num_events = int(sys.stdin.readline())
        process_events(num_events)
if __name__ == '__main__':
    main()

Solution (Python):
import sys
input = sys.stdin.readline
T = int(input())
for _ in range(T):
    q = int(input())
    L = 1
    R = float('inf')
    result = []
    for _ in range(q):
        A = list(map(int, input().split()))
        t = A[0]
        if t == 1:
            (a, b, n) = A[1:]
            if n == 1:
                (left, right) = (1, a)
            else:
                (left, right) = ((n - 1) * a - (n - 2) * b + 1, n * a - (n - 1) * b)
            if left > R or right < L:
                result.append(0)
            else:
                L = max(L, left)
                R = min(R, right)
                result.append(1)
        else:
            (a, b) = A[1:]
            if a >= R:
                result.append(1)
            else:
                nmin = (L - 1 - b) // (a - b) + 1
                nmax = (R - 1 - b) // (a - b) + 1
                if nmin == nmax:
                    result.append(nmin)
                else:
                    result.append(-1)
    print(' '.join(map(str, result)))

Solution (Python):
import sys
Y = lambda : map(int, sys.stdin.readline().split())
for _ in range(*Y()):
    L = 0
    H = 9 ** 20
    for __ in range(*Y()):
        r = Y()
        if next(r) < 2:
            (a, b, n) = r
            v = a + 1 + (n - 2) * (a - b) if n > 1 else 1
            w = a + (n - 1) * (a - b) if n > 1 else a
            if L:
                if v > H or w < L:
                    print(0)
                    continue
                L = max(L, v)
                H = min(H, w)
            else:
                L = v
                H = w
            print(1)
        else:
            (a, b) = r
            v = 2 + (L - a - 1) // (a - b) if L > a else 1
            w = 2 + (H - a - 1) // (a - b) if H > a else 1
            print(-1 if v != w else v)