Problem:


Score : 600 points

Problem Statement

There are N robots numbered 1 to N placed on a number line. Robot i is placed at coordinate X_i. When activated, it will travel the distance of D_i in the positive direction, and then it will be removed from the number line. All the robots move at the same speed, and their sizes are ignorable.

Takahashi, who is a mischievous boy, can do the following operation any number of times (possibly zero) as long as there is a robot remaining on the number line.

Choose a robot and activate it. This operation cannot be done when there is a robot moving.

While Robot i is moving, if it touches another robot j that is remaining in the range [X_i, X_i + D_i) on the number line, Robot j also gets activated and starts moving. This process is repeated recursively.

How many possible sets of robots remaining on the number line are there after Takahashi does the operation some number of times? Compute this count modulo 998244353, since it can be enormous.

Constraints

1 \leq N \leq 2 \times 10^5

-10^9 \leq X_i \leq 10^9

1 \leq D_i \leq 10^9

X_i \neq X_j (i \neq j)

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
X_1 D_1
:
X_N D_N

Output

Print the number of possible sets of robots remaining on the number line, modulo 998244353.

Sample Input 1

2
1 5
3 3

Sample Output 1

3

There are three possible sets of robots remaining on the number line: \{1, 2\}, \{1\}, and \{\}.

These can be achieved as follows:

If Takahashi activates nothing, the robots \{1, 2\} will remain.

If Takahashi activates Robot 1, it will activate Robot 2 while moving, after which there will be no robots on the number line. This state can also be reached by activating Robot 2 and then Robot 1.

If Takahashi activates Robot 2 and finishes doing the operation, the robot \{1\} will remain.

Sample Input 2

3
6 5
-1 10
3 3

Sample Output 2

5

There are five possible sets of robots remaining on the number line: \{1, 2, 3\}, \{1, 2\}, \{2\}, \{2, 3\}, and \{\}.

Sample Input 3

4
7 10
-10 3
4 3
-4 3

Sample Output 3

16

None of the robots influences others.

Sample Input 4

20
-8 1
26 4
0 5
9 1
19 4
22 20
28 27
11 8
-3 20
-25 17
10 4
-18 27
24 28
-11 19
2 27
-2 18
-1 12
-24 29
31 29
29 7

Sample Output 4

110

Remember to print the count modulo 998244353.



Sample input:
2
1 5
3 3


Sample output:
3

Submission status: Time Limit Exceeded

Solution code:
import bisect


def seginit(size, init_value=-100000000):
    n = 2 ** ((size-1).bit_length())
    treesize = n * 2
    st = [init_value for i in range(treesize)]
    return st


def segupdate(st, key, value):
    n = len(st) // 2
    k = key + n
    st[k] = value
    k >>= 1
    while k > 0:
        st[k] = max(st[k * 2], st[k * 2 + 1])
        k >>= 1


def segquery(st, a, b, init_value=-100000000):
    if a > b:
        raise ValueError("a must be less than equal b.")
    l = init_value
    r = init_value
    n = len(st) // 2
    a += n
    b += n
    while a < b:
        if a & 1 == 1:
            l = max(l, st[a])
            a += 1
        if b & 1 == 1:
            b -= 1
            r = max(r, st[b])
        a >>= 1
        b >>= 1
    return max(l, r)


def segview(st, size):
    n = len(st) >> 1
    return st[n:n+size]
    

class Robot():

    def __init__(self, x, d):
        self.x = x
        self.d = d
    
    def __str__(self):
        return "({}, {})".format(self.x, self.d)
    
    def __repr__(self):
        return str(self)

    def __eq__(self, another):
        return self.x == another.x

    def __lt__(self, another):
        return self.x < another.x


def read():
    N = int(input().strip())
    robots = list()
    for i in range(N):
        x, d = list(map(int, input().strip().split()))
        robots.append(Robot(x, d))
    return N, robots


def solve(N, robots, MOD=998244353):
    dp = [0 for i in range(N+1)]
    dp[N] = 1
    robots = list(sorted(robots))
    rx = [robot.x for robot in robots]
    rdx = [robot.x + robot.d for robot in robots]
    # parent_idx = [i for i in range(N)]  # ここを工夫する
    parent_idx = seginit(N)
    for i in range(N):
        segupdate(parent_idx, i, i)

    for i in range(N-1, -1, -1):
        j = bisect.bisect_left(rx[i:], rdx[i])
        mv = segquery(parent_idx, i, i+j)
        segupdate(parent_idx, i, mv)
        dp[i] = dp[i+1] + dp[mv+1]
        dp[i] %= MOD
    return dp[0]


if __name__ == '__main__':
    inputs = read()
    print("{}".format(solve(*inputs)))

Submission status: Time Limit Exceeded

Solution code:
from bisect import bisect_left
n = int(input())
x_d = []
for _ in range(n):
    x_d.append(tuple(map(int, input().split())))
x_d.sort(key=lambda t: t[0])
x = [t[0] for t in x_d]
xplusd = [t[0] + t[1] for t in x_d]
shortright = [bisect_left(x, xpdi) for xpdi in xplusd]
right = [t for t in shortright]
for i in range(n - 1, -1, -1):
    right[i] = max(right[i : right[i]])
dp = [None] * n
dp.append(1)
for i in range(n - 1, -1, -1):
    dp[i] = (dp[i + 1] + dp[right[i]]) % 998244353
print(dp[0])

Submission status: Time Limit Exceeded

Solution code:
import bisect
from collections import deque


class SegmentTree():
    """セグメント木の実装"""

    def __init__(self, size, INF=-100000000):
        """セグメント木の初期化"""
        self.size = size
        self.n = 2 ** ((self.size-1).bit_length())
        self.treesize = 2 * self.n - 1
        self.inf = INF
        self.tree = [self.inf for i in range(self.treesize)]

    def update(self, key, value):
        """key番目の値をvalueに更新する"""
        k = key + self.n - 1
        self.tree[k] = value
        while k > 0:
            k = (k - 1) // 2
            self.tree[k] = max(self.tree[2 * k + 1], self.tree[2 * k + 2])
        
    def query(self, a, b):
        """区間[a, b)の最大値を求める"""
        if a > b:
            raise ValueError("a must be less than equal b.")
        q = deque()
        q.append((0, 0, self.n))
        s = deque()
        while len(q) > 0:
            k, l, r = q.pop()
            if r <= a or b <= l:
                continue
            elif a <= l and r <= b:
                s.append(self.tree[k])
            else:
                q.append((2 * k + 1, l, (l + r) // 2))
                q.append((2 * k + 2, (l + r) // 2, r))
        return max(s)
    
    def __setitem__(self, key, value):
        self.update(key, value)

    def __getitem__(self, key):
        left = self.treesize >> 1
        return self.tree[left + key]
    
    def tolist(self):
        left = self.treesize >> 1
        right = left + self.size
        return self.tree[left:right] 

    def __str__(self):
        return str(self.tolist())
    
    def __repr__(self):
        return str(self)
    


class Robot():

    def __init__(self, x, d):
        self.x = x
        self.d = d
    
    def __str__(self):
        return "({}, {})".format(self.x, self.d)
    
    def __repr__(self):
        return str(self)

    def __eq__(self, another):
        return self.x == another.x

    def __lt__(self, another):
        return self.x < another.x


def read():
    N = int(input().strip())
    robots = list()
    for i in range(N):
        x, d = list(map(int, input().strip().split()))
        robots.append(Robot(x, d))
    return N, robots


def solve(N, robots, MOD=998244353):
    dp = [0 for i in range(N+1)]
    dp[N] = 1
    robots = list(sorted(robots))
    rx = [robot.x for robot in robots]
    rdx = [robot.x + robot.d for robot in robots]
    # parent_idx = [i for i in range(N)]  # ここを工夫する
    parent_idx = SegmentTree(N)
    for i in range(N):
        parent_idx[i] = i
    
    for i in range(N-1, -1, -1):
        # 区間[x, x+d) にある全要素 R[i+1: i+j] を探す
        j = bisect.bisect_left(rx[i:], rdx[i])
        # parent_idx[i] = max(parent_idx[i:i+j])
        mv = parent_idx.query(i, i+j)
        parent_idx[i] = mv

    for i in range(N-1, -1, -1):
        dp[i] = dp[i+1] + dp[parent_idx[i]+1]
        dp[i] %= MOD
    return dp[0]


if __name__ == '__main__':
    inputs = read()
    print("{}".format(solve(*inputs)))

Submission status: Time Limit Exceeded

Solution code:
import sys
sys.setrecursionlimit(10 ** 7)

N = int(input())
XD = [[int(i) for i in input().split()] for _ in range(N)]
XD.sort()
MOD = 998244353
sorted_X = [X for X,_ in XD]

edge = [[] for _ in range(N)]

from bisect import bisect_left

parent = [-1] * N

for i in range(N-1, -1, -1):
    idx = bisect_left(sorted_X, XD[i][0] + XD[i][1])
    for j in range(i+1, idx):
        if parent[j] < 0:
            parent[j] = i

for i,par in enumerate(parent):
    if par < 0:
        continue
    edge[par].append(i)

def cnt(node):
    if not edge[node]:
        return 2
    
    res = 1
    for v in edge[node]:
        res = (res * cnt(v)) % MOD
    res += 1

    return res % MOD

ans = 1
for i,par in enumerate(parent):
    if par < 0:
        ans = (ans * cnt(i)) % MOD

print(ans)

Submission status: Time Limit Exceeded

Solution code:
N = int(input())

XD = [-1 for i in range(N)]


for i in range(N):
    #XD[i] = list(map(int, input().split()))
    XD[i] = tuple(map(int, input().split()))
    #XD[i].append(XD[i][0]+XD[i][1])

#print (XD)
XD.sort()
#print (XD)

R = [-1 for i in range(N)]
for i in range(N-1, -1, -1):
    v = i
    for j in range(i+1, N):
        if XD[i][0]+XD[i][1] > XD[j][0]:
            v = max(v, R[j])
        else:
            break
    R[i] = v
#print (R)

num = [-1 for i in range(N+1)]
num[N] = 1
num[N-1] = 2

for i in range(N-2, -1, -1):
    num[i] = (num[i+1] + num[R[i]+1]) % 998244353
print(num[0])

Submission status: Time Limit Exceeded

Solution code:
N = int(input())

XD = [-1 for i in range(N)]


for i in range(N):
    XD[i] = list(map(int, input().split()))
    #XD[i].append(XD[i][0]+XD[i][1])

#print (XD)
XD.sort()
#print (XD)

R = [-1 for i in range(N)]
for i in range(N-1, -1, -1):
    v = i
    for j in range(i+1, N):
        if XD[i][0]+XD[i][1] > XD[j][0]:
            v = max(v, R[j])
        else:
            break
    R[i] = v
#print (R)

num = [-1 for i in range(N+1)]
num[N] = 1
num[N-1] = 2

for i in range(N-2, -1, -1):
    num[i] = (num[i+1] + num[R[i]+1]) % 998244353
print(num[0])

Submission status: Time Limit Exceeded

Solution code:
N = int(input())

XD = [-1 for i in range(N)]


for i in range(N):
    XD[i] = list(map(int, input().split()))
    XD[i].append(XD[i][0]+XD[i][1])

#print (XD)
XD.sort()
#print (XD)

R = [-1 for i in range(N)]
for i in range(N-1, -1, -1):
    v = i
    for j in range(i+1, N):
        if XD[i][0]+XD[i][1] > XD[j][0]:
            v = max(v, R[j])
        else:
            break
    R[i] = v
#print (R)

num = [-1 for i in range(N+1)]
num[N] = 1
num[N-1] = 2

for i in range(N-2, -1, -1):
    num[i] = (num[i+1] + num[R[i]+1]) % 998244353
print(num[0])

Submission status: Time Limit Exceeded

Solution code:
N = int(input())

XD = [-1 for i in range(N)]


for i in range(N):
    XD[i] = list(map(int, input().split()))
    XD[i].append(XD[i][0]+XD[i][1])

#print (XD)
XD.sort()
#print (XD)

R = [-1 for i in range(N)]
for i in range(N-1, -1, -1):
    v = i
    for j in range(i+1, N):
        if XD[i][0]+XD[i][1] > XD[j][0]:
            v = max(v, R[j])
        #else:
        #    break
    R[i] = v
#print (R)

num = [-1 for i in range(N+1)]
num[N] = 1
num[N-1] = 2

for i in range(N-2, -1, -1):
    num[i] = (num[i+1] + num[R[i]+1]) % 998244353
print(num[0])

Submission status: Time Limit Exceeded

Solution code:
# 解説放送

def main():
    from collections import deque, namedtuple
    from operator import attrgetter
    import sys
    sys.setrecursionlimit(10 ** 7)
    input = sys.stdin.readline

    MOD = 998244353

    Robot = namedtuple('Robot', 'x d reach ind')

    N = int(input())

    robots = []
    for ind in range(N):
        X, D = map(int, input().split())
        robots.append(Robot(X, D, X + D, ind))

    graph = tuple(set() for _ in range(N))  # DAG, graph[robot.ind]={robot.ind,...}
    to_candidates = deque()
    for robot_from in sorted(robots, key=attrgetter('x'), reverse=True):
        """
        右端に位置するロボットから順に「起点」と見なしていく
        既出のロボットで有向辺の行き先として一度も設定されていないものが
        to_candidatesにx昇順で溜められている
        to_candidatesに含まれるロボットで「起点」から接触範囲内のものがある限り、
        「起点」から有向辺を張り続ける
        to_candidatesの先頭候補(最も左側に位置する)に対して辺を張れない場合、
        それ以降の候補のxはより遠い座標で辺を張れないので
        「起点」から張れる辺がないとわかる
        すべてのロボットは「起点」から辺を張られてto_candidatesから外れるか
        to_candidatesに残り、グラフ(森)の各木のrootとなる
        """
        while to_candidates:
            robot_to = to_candidates[0]
            if robot_to.x < robot_from.reach:
                graph[robot_from.ind].add(robot_to.ind)
                to_candidates.popleft()
            else:
                break

        to_candidates.appendleft(robot_from)

    def dfs(v):
        """有向グラフで親に遡ることはないので到達フラグ管理は不要"""
        ret = 1
        for u in graph[v]:
            ret = (ret * dfs(u)) % MOD
        return ret + 1

    root_robots = to_candidates
    ret = 1
    for root_robot in root_robots:
        ret = (ret * dfs(root_robot.ind)) % MOD
    print(ret)
    return


if __name__ == '__main__':
    main()

Submission status: Time Limit Exceeded

Solution code:
from heapq import *
import sys

sys.setrecursionlimit(10 ** 6)
int1 = lambda x: int(x) - 1
p2D = lambda x: print(*x, sep="\n")
def II(): return int(sys.stdin.readline())
def MI(): return map(int, sys.stdin.readline().split())
def LI(): return list(map(int, sys.stdin.readline().split()))
def LLI(rows_number): return [LI() for _ in range(rows_number)]
def SI(): return sys.stdin.readline()[:-1]

class mint:
    def __init__(self, x):
        self.__x = x % md

    def __str__(self):
        return str(self.__x)

    def __add__(self, other):
        if isinstance(other, mint): other = other.__x
        return mint(self.__x + other)

    def __sub__(self, other):
        if isinstance(other, mint): other = other.__x
        return mint(self.__x - other)

    def __rsub__(self, other):
        return mint(other - self.__x)

    def __mul__(self, other):
        if isinstance(other, mint): other = other.__x
        return mint(self.__x * other)

    __radd__ = __add__
    __rmul__ = __mul__

    def __truediv__(self, other):
        if isinstance(other, mint): other = other.__x
        return mint(self.__x * pow(other, md - 2, md))

    def __rtruediv__(self, other):
        return mint(other * pow(self.__x, md - 2, md))

    def __pow__(self, power, modulo=None):
        return mint(pow(self.__x, power, md))

md = 998244353

def main():
    def dfs(i):
        res=mint(1)
        for j in to[i]:
            res*=dfs(j)
        return res+1

    n=II()
    xd=LLI(n)
    xd.sort(reverse=True)
    to=[[] for _ in range(n)]
    hp=[]
    for i,(x,d) in enumerate(xd):
        while hp and hp[0][0]<x+d:
            px,pi=heappop(hp)
            to[i].append(pi)
        heappush(hp,(x,i))
    ans=1
    while hp:
        _,i=heappop(hp)
        ans*=dfs(i)
    print(ans)

main()

Submission status: Time Limit Exceeded

Solution code:
import sys
sys.setrecursionlimit(10**6)
from operator import itemgetter
import bisect
def main():
    input = sys.stdin.readline
    N = int(input())
    XD = [tuple(map(int, input().split())) for _ in range(N)]
    MOD = 998244353

    XD.sort(key=itemgetter(0))
    X = [xd[0] for xd in XD]

    E = [[] for _ in range(N)]
    j = 0
    for i in range(N):
        x, d = XD[i]
        j = bisect.bisect_left(X, x+d, i)
        for k in range(i+1, j):
            E[i].append(k)

    parent = [-1] * N
    values = [Mint(1, MOD) for _ in range(N)]
    def f(i):
        stack = [(i, 0)]
        while stack:
            v, k = stack.pop()
            if k < len(E[v]):
                while k < len(E[v]):
                    to = E[v][k]
                    if parent[to] < 0:
                        parent[to] = v
                        stack.append((v, k+1))
                        stack.append((to, 0))
                        break
                    k += 1
                else:
                    stack.append((v, len(E[v])))
            else:
                values[v] += 1
                if parent[v] != v:
                    values[parent[v]] *= values[v]
        return values[i]

    ans = Mint(1, MOD)
    for i in range(N):
        if parent[i] >= 0: continue
        parent[i] = i
        ans *= f(i)
    print(ans)


class Mint:
    def __init__(self, value=0, mod=10**9+7):
        self.value = ((value % mod) + mod) % mod
        self.mod = mod

    @staticmethod
    def get_value(x): return x.value if isinstance(x, Mint) else x

    def inverse(self):
        a, b = self.value, self.mod
        u, v = 1, 0
        while b:
            t = a // b
            b, a = a - t * b, b
            v, u = u - t * v, v
        return (u + self.mod) % self.mod

    def __repr__(self): return str(self.value)
    def __eq__(self, other): return self.value == other.val
    def __neg__(self): return Mint(-self.value, self.mod)
    def __hash__(self): return hash(self.value)
    def __bool__(self): return self.value != 0

    def __iadd__(self, other):
        self.value = (self.value + Mint.get_value(other)) % self.mod
        return self
    def __add__(self, other):
        new_obj = Mint(self.value, self.mod)
        new_obj += other
        return new_obj
    __radd__ = __add__

    def __isub__(self, other):
        self.value = (self.value - Mint.get_value(other) + self.mod) % self.mod
        return self
    def __sub__(self, other):
        new_obj = Mint(self.value, self.mod)
        new_obj -= other
        return new_obj
    def __rsub__(self, other):
        new_obj = Mint(Mint.get_value(other), self.mod)
        new_obj -= self
        return new_obj

    def __imul__(self, other):
        self.value = self.value * Mint.get_value(other) % self.mod
        return self
    def __mul__(self, other):
        new_obj = Mint(self.value, self.mod)
        new_obj *= other
        return new_obj
    __rmul__ = __mul__

    def __ifloordiv__(self, other):
        other = other if isinstance(other, Mint) else Mint(other, self.mod)
        self *= other.inverse
        return self
    def __floordiv__(self, other):
        new_obj = Mint(self.value, self.mod)
        new_obj //= other
        return new_obj
    def __rfloordiv__(self, other):
        new_obj = Mint(Mint.get_value(other), self.mod)
        new_obj //= self
        return new_obj

if __name__ == '__main__':
    main()

Submission status: Time Limit Exceeded

Solution code:
# 解説放送

def main():
    from collections import deque, namedtuple
    from operator import attrgetter
    import sys
    sys.setrecursionlimit(10 ** 7)
    input = sys.stdin.readline

    MOD = 998244353

    Robot = namedtuple('Robot', 'x d ind')

    N = int(input())

    robots = []
    for ind in range(N):
        X, D = map(int, input().split())
        robots.append(Robot(X, D, ind))
    robots.sort(key=attrgetter('x'), reverse=True)

    graph = tuple(set() for _ in range(N))  # DAG

    to_candidates = deque()
    buffer = deque()

    def is_in_range(robot_from, x):
        return robot_from.x <= x < robot_from.x + robot_from.d

    for robot_from in robots:
        if not to_candidates:
            to_candidates.append(robot_from)
            continue

        while to_candidates:
            robot_to = to_candidates.popleft()
            if is_in_range(robot_from, robot_to.x):
                graph[robot_from.ind].add(robot_to.ind)
            else:
                buffer.append(robot_to)
        else:
            to_candidates = buffer
            buffer = deque()

        to_candidates.append(robot_from)

    checked = [0] * N

    def dfs(v):
        ret = 1
        for u in graph[v]:
            if checked[u]: continue
            checked[u] = 1
            ret = (ret * dfs(u)) % MOD
        ret += 1
        return ret

    root_robots = to_candidates
    ret = 1
    for root_robot in root_robots:
        ret = (ret * dfs(root_robot.ind)) % MOD
    print(ret)
    return


if __name__ == '__main__':
    main()

Submission status: Time Limit Exceeded

Solution code:
#!/usr/bin/env python3
import sys, math, itertools, collections, bisect
input = lambda: sys.stdin.buffer.readline().rstrip().decode('utf-8')
inf = float('inf') ;mod = 998244353
mans = inf ;ans = 0 ;count = 0 ;pro = 1
sys.setrecursionlimit(10**6)

n = int(input())
XD = [(-10**10,inf)]
for i in range(n):
  x,d = map(int,input().split())
  XD.append((x,d))
XD.sort()
visited = [0] * (n+1)
def dfs(node):
  visited[node] = 1
  res = 1
  i = node + 1
  while i < n+1:
    if XD[i][0] < XD[node][0] + XD[node][1]:
      if visited[i]:continue
      pro,i = dfs(i)
      res *= pro
      res %= mod
    else: break
  # print(node,res+1)
  return res + 1 , i
print((dfs(0)[0]-1)%mod)
# print(visited)
# print(XD)
# dfs(1)

Submission status: Time Limit Exceeded

Solution code:
#!/usr/bin/env python3
import sys, math, itertools, collections, bisect
input = lambda: sys.stdin.buffer.readline().rstrip().decode('utf-8')
inf = float('inf') ;mod = 998244353
mans = inf ;ans = 0 ;count = 0 ;pro = 1
sys.setrecursionlimit(10**6)

n = int(input())
# XD = [tuple(map(int,input().split())) for i in range(n)]
XD = [(-10**10,inf)]
for i in range(n):
  x,d = map(int,input().split())
  XD.append((x,d))
XD.sort()
visited = [0] * (n+1)
def dfs(node):
  visited[node] = 1
  res = 1
  for i in range(node+1,n+1):
    if XD[i][0] < XD[node][0] + XD[node][1]:
      if visited[i]:continue
      res *= dfs(i)
      res %= mod
    else: break
  # print(node,res+1)
  return res + 1
print((dfs(0)-1)%mod)
# print(visited)
# print(XD)
# dfs(1)

Submission status: Time Limit Exceeded

Solution code:
import bisect


class SegmentTree():
    """セグメント木の実装"""

    def __init__(self, size, INF=100000000):
        """セグメント木の初期化"""
        self.size = size
        n = 1
        while n < size:
            n <<= 1
        self.n = n
        self.treesize = 2 * self.n - 1
        self.tree = [-INF for i in range(self.treesize)]
        self.inf = INF
    
    def __setitem__(self, key, value):
        self.update(key, value)

    def update(self, key, value):
        """key番目の値をvalueに更新する"""
        k = key + self.n - 1
        self.tree[k] = value
        while k > 0:
            k = (k - 1) // 2
            self.tree[k] = max(self.tree[2 * k + 1], self.tree[2 * k + 2])
    
    def query(self, a, b):
        """区間[a, b)の最大値を求める"""
        if a > b:
            raise ValueError("a must be less than equal b.")
        return self.__query(a, b, 0, 0, self.n)
    
    def __query(self, a, b, k, l, r):
        if r <= a or b <= l:
            return -self.inf
        if a <= l and r <= b:
            return self.tree[k]
        else:
            vl = self.__query(a, b, 2 * k + 1, l, (l + r) // 2)
            vr = self.__query(a, b, 2 * k + 2, (l + r) // 2, r)
            return max(vl, vr)
    
    def __getitem__(self, key):
        return self.tree[self.treesize - self.n + key]

    def __str__(self):
        return str(self.tree[self.treesize - self.n:self.treesize - self.n + self.size])
    
    def __repr__(self):
        return str(self)


class Robot():

    def __init__(self, x, d):
        self.x = x
        self.d = d
    
    def __str__(self):
        return "({}, {})".format(self.x, self.d)
    
    def __repr__(self):
        return str(self)

    def __eq__(self, another):
        return self.x == another.x

    def __lt__(self, another):
        return self.x < another.x


def read():
    N = int(input().strip())
    robots = list()
    for i in range(N):
        x, d = list(map(int, input().strip().split()))
        robots.append(Robot(x, d))
    return N, robots


def solve(N, robots, MOD=998244353):
    dp = [0 for i in range(N+1)]
    dp[N] = 1
    robots = list(sorted(robots))
    rx = [robot.x for robot in robots]
    rdx = [robot.x + robot.d for robot in robots]
    # parent_idx = [i for i in range(N)]  # ここを工夫する
    parent_idx = SegmentTree(N)
    for i in range(N):
        parent_idx[i] = i
    
    for i in range(N-1, -1, -1):
        # 区間[x, x+d) にある全要素 R[i+1: i+j] を探す
        j = bisect.bisect_left(rx[i:], rdx[i])
        # parent_idx[i] = max(parent_idx[i:i+j])
        mv = parent_idx.query(i, i+j)
        parent_idx[i] = mv

    for i in range(N-1, -1, -1):
        dp[i] = dp[i+1] + dp[parent_idx[i]+1]
        dp[i] %= MOD
    return dp[0]


if __name__ == '__main__':
    inputs = read()
    print("{}".format(solve(*inputs)))

Submission status: Time Limit Exceeded

Solution code:
import bisect


class Robot():

    def __init__(self, x, d):
        self.x = x
        self.d = d
    
    def __str__(self):
        return "({}, {})".format(self.x, self.d)
    
    def __repr__(self):
        return str(self)

    def __eq__(self, another):
        return self.x == another.x

    def __lt__(self, another):
        return self.x < another.x


def read():
    N = int(input().strip())
    robots = list()
    for i in range(N):
        x, d = list(map(int, input().strip().split()))
        robots.append(Robot(x, d))
    return N, robots


def solve(N, robots, MOD=998244353):
    dp = [0 for i in range(N+1)]
    dp[N] = 1
    robots = list(sorted(robots))
    rx = [robot.x for robot in robots]
    rdx = [robot.x + robot.d for robot in robots]
    parent_idx = [i for i in range(N)]
    for i in range(N-1, -1, -1):
        # 区間[x, x+d) にある全要素 R[i+1: i+j] を探す
        j = bisect.bisect_left(rx[i:], rdx[i])
        parent_idx[i] = max(parent_idx[i:i+j])

    for i in range(N-1, -1, -1):
        dp[i] = dp[i+1] + dp[parent_idx[i]+1]
        dp[i] %= MOD
    return dp[0]

if __name__ == '__main__':
    inputs = read()
    print("{}".format(solve(*inputs)))

Submission status: Time Limit Exceeded

Solution code:
class SegTree:
    def __init__(self, init_val, ide_ele, seg_func):
        self.segfunc = seg_func
        n = len(init_val)
        self.num = 2**(n-1).bit_length()
        self.ide_ele = ide_ele
        self.seg=[self.ide_ele]*2*self.num
        for i in range(n):
            self.seg[i+self.num-1]=init_val[i]    
        for i in range(self.num-2,-1,-1) :
            self.seg[i]=self.segfunc(self.seg[2*i+1],self.seg[2*i+2]) 
        
    def update(self, k, x):
        k += self.num-1
        self.seg[k] = x
        # k+1ではなくkでは？
        while k+1:
            k = (k-1)//2
            self.seg[k] = self.segfunc(self.seg[k*2+1],self.seg[k*2+2])
        
    def query(self, p, q):
        if q<=p:
            return self.ide_ele
        p += self.num-1
        q += self.num-2
        res=self.ide_ele
        while q-p>1:
            if p&1 == 0:
                res = self.segfunc(res,self.seg[p])
            if q&1 == 1:
                res = self.segfunc(res,self.seg[q])
                q -= 1
            p = p//2
            q = (q-1)//2
        if p == q:
            res = self.segfunc(res,self.seg[p])
        else:
            res = self.segfunc(self.segfunc(res,self.seg[p]),self.seg[q])
        return res
N=int(input())
X = []
Y = []
for _ in range(N):
    x, d = map(int, input().split())
    X.append((x,d))

X.sort(key=lambda x:x[0])
for i, (x, d) in enumerate(X):
    Y.append((2*x,i,0))
    Y.append((2*x+2*d-1,i,1))

Y.sort(key=lambda x:x[0])
C = [0]*N
for x, i, t in Y:
    if t==0:
        j = i
    elif t==1:
        C[i] = j
st = SegTree(C, -1, max)
for i in range(N-1, -1, -1):
    x, d = X[i]
    y=st.query(i, C[i]+1)
    st.update(i, y)
    C[i] = y

dp = [[0, 1] for _ in range(N+1)]
for i in range(N-1, -1, -1):
    dp[i][0] = sum(dp[i+1])
#    print(C[i]+1)
    dp[i][1] = sum(dp[C[i]+1])
print(sum(dp[0]))

Submission status: Time Limit Exceeded

Solution code:
printn = lambda x: print(x,end='')
inn = lambda : int(input())
inl   = lambda: list(map(int, input().split()))
inm   = lambda:      map(int, input().split())
ins = lambda : input().strip()
DBG = True  and False
BIG = 10**18
R = 998244353

def ddprint(x):
  if DBG:
    print(x)



# # # # class Segtree # # # #

#      0
#   1     2
# 3   4  5  6
#       :
# leaf i - n-1+i
# parent   - (i-1)//2
# children - 2*i+1, 2*i+2

class Segtree:
    # modify UNIT and oper depending on the reduce operation

    #UNIT = 0  # sum/or:0 and:fff..f min:BIG max:-BIG gcd:0 lcm:1 ..

    #@classmethod
    #def oper(c,x,y):
    #    return x|y  # sum:+ or/and/min/max/gcd/lcm:(same)

    # call like this: sgt = Segtree(n, 0, lambda x,y: max(x,y))

    def __init__(s,l,unit,oper):
        s.unit = unit
        s.oper = oper
        s.n = 1
        while s.n<l:
            s.n *= 2
        s.ary = [s.unit for i in range(2*s.n-1)]

    def get(s,i):
        return s.ary[i+s.n-1]

    def set(s,i,v):
        k = i+s.n-1
        s.ary[k] = v
        while k>0:
            k = (k-1)//2
            s.ary[k] = s.oper( \
                        s.ary[2*k+1], s.ary[2*k+2])

    def setary(s,a):
        for i,v in enumerate(a):
            s.ary[i+s.n-1] = v
        for k in range(s.n-2,-1,-1):
            s.ary[k] = s.oper( \
                        s.ary[2*k+1], s.ary[2*k+2])

    def query(s,x,y):
        l = x+s.n-1
        r = y+s.n-1
        res = s.unit
        while l<r:
            if not l%2:
                res = s.oper(res,s.ary[l])
                l += 1
            if not r%2:
                r -= 1
                res = s.oper(res,s.ary[r])
            l >>= 1
            r >>= 1
        return res


# # # # class Segtree end # # # #

# # # #
from bisect import bisect_left
n = inn()
xd = []
for i in range(n):
    xx,dd = inm()
    xd.append((xx,dd))
xd.sort()
x = [xd[i][0] for i in range(n)]

#ddprint(xd)
#ddprint(x)

r = [i for i in range(n)]
sgt = Segtree(n,0,lambda x,y: max(x,y))
sgt.setary(r)
f = [0]*(n+1)
f[n] = 1
f[n-1] = 2
for i in range(n-2,-1,-1):
    xx,dd = xd[i]
    j = bisect_left(x,xx+dd)
    k = sgt.query(i,j)
    sgt.set(i,k)
    f[i] = (f[i+1] + f[k+1])%R
    #ddprint(f"i {i} x {xx} d {dd} j {j}")

#ddprint(f)
print(f[0])

Submission status: Time Limit Exceeded

Solution code:
n = int(input())
xd = []
for i in range(n):
    x, d = map(int, input().split())
    xd.append((x, d))
xd.sort(key=lambda a: a[0])

X = 998244353
es = []
for i, (x, d) in enumerate(xd):
    es.append((x, False, i))
    es.append((x + d - 0.5, True, i))
es.sort(key=lambda a: a[0])

back = [None] * n
last = None
last_id = None
for p, f, i in es:
    if f:
        back[i] = last_id + 1
    else:
        last_id = i

for i in range(n):
    b = back[n - i - 1]
    b2 = back[b - 1]
    back[n - i - 1] = max(back[n - i - 1:b])

cnt = [0] * (n + 1)
cnt[-1] = 1
for i in range(n):
    b = back[n - i - 1]
    back_cnt = cnt[b]
    score = back_cnt + cnt[n - i]
    while score >= X:
        score -= X
    cnt[n - i - 1] = score
print(cnt[0])