Tourist (Codeforces 76F)
Tags: DP, binary search

Tourist walks along the X axis. He can choose either of two directions and any speed not exceeding V. He can also stand without moving anywhere. He knows from newspapers that at time t1 in the point with coordinate x1 an interesting event will occur, at time t2 in the point with coordinate x2 — another one, and so on up to (xn, tn). Interesting events are short so we can assume they are immediate. Event i counts visited if at time ti tourist was at point with coordinate xi.Write program tourist that will find maximum number of events tourist if:   at the beginning (when time is equal to 0) tourist appears at point 0,  tourist can choose initial point for himself. Yes, you should answer on two similar but different questions.

Input: The first line of input contains single integer number N (1 ≤ N ≤ 100000) — number of interesting events. The following N lines contain two integers xi and ti — coordinate and time of the i-th event. The last line of the input contains integer V — maximum speed of the tourist. All xi will be within range  - 2·108 ≤ xi ≤ 2·108, all ti will be between 1 and 2·106 inclusive. V will be positive and will not exceed 1000. The input may contain events that happen at the same time or in the same place but not in the same place at the same time.

Output: The only line of the output should contain two space-sepatated integers — maximum number of events tourist can visit in he starts moving from point 0 at time 0, and maximum number of events tourist can visit if he chooses the initial point for himself.


Sample Inputs:
3
-1 1
42 7
40 8
2

Sample Outputs:
1 2

Solution (Python):
import decimal
import heapq
import math
import os
import sys
from collections import Counter, deque
from io import BytesIO, IOBase
import bisect
from types import GeneratorType
BUFSIZE = 8192

class FastIO(IOBase):
    newlines = 0

    def __init__(self, file):
        self._fd = file.fileno()
        self.buffer = BytesIO()
        self.writable = 'x' in file.mode or 'r' not in file.mode
        self.write = self.buffer.write if self.writable else None

    def read(self):
        while True:
            b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
            if not b:
                break
            ptr = self.buffer.tell()
            (self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
        self.newlines = 0
        return self.buffer.read()

    def readline(self):
        while self.newlines == 0:
            b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
            self.newlines = b.count(b'\n') + (not b)
            ptr = self.buffer.tell()
            (self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
        self.newlines -= 1
        return self.buffer.readline()

    def flush(self):
        if self.writable:
            os.write(self._fd, self.buffer.getvalue())
            (self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

    def __init__(self, file):
        self.buffer = FastIO(file)
        self.flush = self.buffer.flush
        self.writable = self.buffer.writable
        self.write = lambda s: self.buffer.write(s.encode('ascii'))
        self.read = lambda : self.buffer.read().decode('ascii')
        self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def isPrime(n):
    if n <= 1:
        return False
    if n <= 3:
        return True
    if n % 2 == 0 or n % 3 == 0:
        return False
    i = 5
    while i * i <= n:
        if n % i == 0 or n % (i + 2) == 0:
            return False
        i = i + 6
    return True

def lcm(a, b):
    return a * b // math.gcd(a, b)

def ints_get():
    return map(int, input().strip().split())

def list_get():
    return list(map(int, sys.stdin.readline().strip().split()))

def chars_get():
    return list(map(str, sys.stdin.readline().strip().split()))

def ipn():
    return int(input())

def bootstrap(f, stack=[]):

    def wrappedfunc(*args, **kwargs):
        if stack:
            return f(*args, **kwargs)
        else:
            to = f(*args, **kwargs)
            while True:
                if type(to) is GeneratorType:
                    stack.append(to)
                    to = next(to)
                else:
                    stack.pop()
                    if not stack:
                        break
                    to = stack[-1].send(to)
            return to
    return wrappedfunc

def main():

    def LIS(arr):
        if len(arr) == 0:
            return 0
        l = [arr[0]]
        for element in arr[1:]:
            pos = bisect.bisect(l, element)
            if pos == len(l):
                if element >= l[pos - 1]:
                    l.append(element)
            else:
                l[pos] = element
        return len(l)
    n = ipn()
    v = []
    for _ in range(n):
        v.append(list_get())
    p = ipn()
    a = []
    for i in v:
        a.append([-1 * i[0] + i[1] * p, i[0] + i[1] * p])
    a.sort()
    x = []
    y = []
    for i in a:
        x.append(i[1])
    for i in a:
        if i[1] >= 0 and i[0] >= 0:
            y.append(i[1])
    print(LIS(y), LIS(x))
    return
if __name__ == '__main__':
    main()

Solution (Python):
import sys
import bisect
(N, V) = (0, 1)
events = []
result = [0, 1]

def read_input():
    global N, V
    readline = sys.stdin.readline
    N = int(readline().rstrip())
    for _ in range(N):
        events.append([int(w) for w in readline().split()])
    V = int(readline().rstrip())

def solve():
    seq = [[t * V - x, t * V + x] for (x, t) in events]
    seq.sort()
    stk = [0]
    for (p, q) in seq:
        if p < 0 or q < 0:
            continue
        idx = bisect.bisect_right(stk, q)
        if idx == len(stk):
            stk.append(q)
        else:
            stk[idx] = q
    result[0] = len(stk) - 1
    stk = []
    for (p, q) in seq:
        idx = bisect.bisect_right(stk, q)
        if idx == len(stk):
            stk.append(q)
        else:
            stk[idx] = q
    result[1] = len(stk)

def write_output():
    print(*result)
read_input()
solve()
write_output()

Solution (Python):
from sys import stdin
input = stdin.buffer.readline
from bisect import bisect
from itertools import zip_longest

def main():
    n = int(input())
    events = [tuple(map(int, input().split())) for _ in range(n)]
    v = int(input())
    (tot, zero) = ([], [])
    for (i, e) in enumerate(events):
        (pos, time) = e
        zero.append(abs(pos) <= v * time)
        tot.append((v * time + pos, v * time - pos))
    order = sorted(range(n), key=lambda i: tot[i])
    (lis1, lis2) = ([], [])
    for i in order:
        (x, y) = tot[i]
        if zero[i]:
            i = bisect(lis1, y)
            if i == len(lis1):
                lis1.append(y)
            else:
                lis1[i] = y
        i = bisect(lis2, y)
        if i == len(lis2):
            lis2.append(y)
        else:
            lis2[i] = y
    print(len(lis1), len(lis2))
main()