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:
from bisect import bisect_right
from bisect import bisect_left
mod = 998244353

n = int(input())
robot = []
pos = []

for i in range(n):
    x, d = map(int, input().split())
    robot.append([x, x+d])
    pos.append(x)

robot = sorted(robot, key=lambda y: y[0])
pos = sorted(pos)


def init(init_val):
    for i in range(n):
        MI[i+num-1] = init_val[i]
        MA[i+num-1] = init_val[i]
    for i in range(num-2, -1, -1):
        MI[i] = min(MI[2*i+1], MI[2*i+2])
        MA[i] = max(MA[2*i+1], MA[2*i+2])


def update(k, x):
    k += num-1
    MI[k] = x
    MA[k] = x
    while k+1:
        k = (k-1)//2
        MI[k] = min(MI[k*2+1], MI[k*2+2])
        MA[k] = max(MA[k*2+1], MA[k*2+2])


def rangemin(p, q):
    if q <= p:
        return 1 << 100
    p += num-1
    q += num-2
    res = 1 << 100
    while q-p > 1:
        if p & 1 == 0:
            res = min(res, MI[p])
        if q & 1 == 1:
            res = min(res, MI[q])
            q -= 1
        p = p//2
        q = (q-1)//2
    if p == q:
        res = min(res, MI[p])
    else:
        res = min(min(res, MI[p]), MI[q])
    return res


def rangemax(p, q):
    if q <= p:
        return -1
    p += num-1
    q += num-2
    res = -1
    while q-p > 1:
        if p & 1 == 0:
            res = max(res, MA[p])
        if q & 1 == 1:
            res = max(res, MA[q])
            q -= 1
        p = p//2
        q = (q-1)//2
    if p == q:
        res = max(res, MA[p])
    else:
        res = max(max(res, MA[p]), MA[q])
    return res


# n:リスト長
num = 2**(n-1).bit_length()
MI = [1 << 100]*2*num
MA = [-1]*2*num

r = []
for x, d in robot:
    r.append(bisect_left(pos, d))

init(r)

s = [0]*n

for x in range(n-1, -1, -1):
    right_max = rangemax(x, r[x])
    s[x] = right_max
    update(x, right_max)

dp = [0]*(n+1)
dp[-1] = 1

for i in range(n-1, -1, -1):
    dp[i] = dp[i+1]+dp[s[i]]

print(dp[0])

Submission status: Time Limit Exceeded

Solution code:
def i1():
 return int(input())
def i2():
 return [int(i) for i in input().split()]
import bisect
import sys
sys.setrecursionlimit(10**6)
mod=998244353
n=i1() 
d=[]
for i in range(n):
  d.append(i2())
d=sorted(d)
dx=[]
dd=[]
for i,j in d:
  dx.append(i)
  dd.append(j)
r=[]
dt=[-1 for i in range(n)]

def ddd(i,dt):
  x=i
  for k in range(i+1,n):
      if dx[k]<dx[i]+dd[i] and dt[k]<0:
         xx,dt=ddd(k,dt)
         x=max(x,xx)
  dt[i]=x
  return x,dt
for i in range(n):
    if dt[i]<0:
      x,dt=ddd(i,dt)
dp=[0 for i in range(n+1)]
dp[-1]=1
for i in range(n)[::-1]:
  dp[i]+=dp[i+1]
  dp[i]+=dp[dt[i]+1]
  dp[i]%=mod
print(dp[0])

Submission status: Time Limit Exceeded

Solution code:
def i1():
 return int(input())
def i2():
 return [int(i) for i in input().split()]
import bisect
import sys
sys.setrecursionlimit(10**6)
mod=998244353
n=i1() 
d=[]
for i in range(n):
  d.append(i2())
d=sorted(d)
dx=[]
dd=[]
for i,j in d:
  dx.append(i)
  dd.append(j)
r=[]
dt=[0 for i in range(n)]
dt[-1]=1
for i in range(n):
 r.append(bisect.bisect_left(dx,dx[i]+dd[i]))


for i in range(n)[::-1]:
  dt[i]=max([i]+dt[i+1:r[i]])      
dp=[0 for i in range(n+1)]
dp[-1]=1
for i in range(n)[::-1]:
  dp[i]+=dp[i+1]
  dp[i]+=dp[dt[i]+1]
  dp[i]%=mod
print(dp[0])

Submission status: Time Limit Exceeded

Solution code:
def i1():
 return int(input())
def i2():
 return [int(i) for i in input().split()]
import bisect
import sys
sys.setrecursionlimit(10**6)
mod=998244353
n=i1() 
d=[]
for i in range(n):
  d.append(i2())
d=sorted(d)
dx=[]
dd=[]
for i,j in d:
  dx.append(i)
  dd.append(j)
r=[]
dt=[0 for i in range(n)]
dt[-1]=1
for i in range(n):
 r.append(bisect.bisect_left(dx,dx[i]+dd[i]))

def ddd(i):
  x=i
  for k in range(i+1,r[i]):
      if dt[k]==0:
         x=max(x,ddd(k))
      else:
         x=max(x,dt[k])
  dt[i]=x
  return x
for i in range(n)[::-1]:
    dt[i]=ddd(i)
dp=[0 for i in range(n+1)]
dp[-1]=1
for i in range(n)[::-1]:
  dp[i]+=dp[i+1]
  dp[i]+=dp[dt[i]+1]
  dp[i]%=mod
print(dp[0])

Submission status: Time Limit Exceeded

Solution code:
def i1():
 return int(input())
def i2():
 return [int(i) for i in input().split()]
import bisect
mod=998244353
n=i1()
d=[]
N=1<<(n.bit_length())
t=[-1 for i in range(2*N-1)]

def ud(i,x):
  i+=N-1
  t[i]=x
  while i:
    i-=1
    i>>=1
    j=i+0
    j<<=1
    t[i]=max(t[j+1],t[j+2]) 
     

def qr(a,b):
    a+=N-1
    b+=N-1
    L = -1
    R = -1
    while a < b:
      if a&1==0:
         L = max(L, t[a])
      if b&1==0:
         b-=1
         R = max(t[b], R)
      
      a>>=1
      b>>=1
      
         
    return max(L, R)
 
for i in range(n):
  d.append(i2())
d=sorted(d)
dx=[]
dd=[]
for i,j in d:
  dx.append(i)
  dd.append(j)
for i in range(n)[::-1]:
 j=bisect.bisect_left(dx,dx[i]+dd[i])
 tt=qr(i,j)
 ud(i,max(j-1,tt))
dp=[0 for i in range(n+1)]
dp[-1]=1
for i in range(n)[::-1]:
  dp[i]+=dp[i+1]
  dp[i]+=dp[t[i+N-1]+1]
  dp[i]%=mod
print(dp[0])

Submission status: Time Limit Exceeded

Solution code:
def i1():
 return int(input())
def i2():
 return [int(i) for i in input().split()]
import bisect
mod=998244353
n=i1()
d=[]
N=1<<(n.bit_length())
t=[-1 for i in range(2*N-1)]

def ud(i,x):
  i+=N-1
  t[i]=x
  while i:
    i=(i-1)//2
    t[i]=max(t[i*2+1],t[i*2+2]) 
     

def qr(a,b):
    a+=N-1
    b+=N-1
    L = -1
    R = -1
    while a < b:
      if a&1==0:
         L = max(L, t[a])
      if b&1==0:
         b-=1
         R = max(t[b], R)
      
      a>>=1
      b>>=1
      
         
    return max(L, R)
 
for i in range(n):
  d.append(i2())
d=sorted(d)
dx=[]
dd=[]
for i,j in d:
  dx.append(i)
  dd.append(j)
for i in range(n)[::-1]:
 j=bisect.bisect_left(dx,dx[i]+dd[i])
 tt=qr(i,j)
 ud(i,max(j-1,tt))
dp=[0 for i in range(n+1)]
dp[-1]=1
for i in range(n)[::-1]:
  dp[i]+=dp[i+1]
  dp[i]+=dp[t[i+N-1]+1]
  dp[i]%=mod
print(dp[0])

Submission status: Time Limit Exceeded

Solution code:
import bisect


class SegTreeMax():
    def __init__(self, l):
        self.N = 1
        while self.N < len(l):
            self.N *= 2
        self.L = [0 for _ in range(self.N*2-1)]
        for i in range(len(l)):
            self.L[i+self.N-1] = l[i]
        for i in range(self.N-2, -1, -1):
            self.L[i] = max(self.L[i*2+1], self.L[i*2+2])

    def update(self, k, v):
        k += self.N-1
        self.L[k] = v
        while k > 0 and self.L[(k-1)//2] < v:
            k = (k-1)//2
            self.L[k] = v

    def query(self, a, b):
        return self.inquiry(0, self.N, 0, a, b)

    def inquiry(self, l, r, k, a, b):
        if r <= a or l >= b:
            return 0
        if a <= l and b >= r:
            return self.L[k]
        vl = self.inquiry(l, (l+r)//2, k*2+1, a, b)
        vr = self.inquiry((l+r)//2, r, k*2+2, a, b)
        return max(vl, vr)


MOD = 998244353
N = int(input())
R = [list(map(int, input().split())) for _ in range(N)]
R.sort(key=lambda x: x[0])
D = [R[i][0] for i in range(N)]
A = [i for i in range(N)]
for i in range(N-1, -1, -1):
    A[i] = bisect.bisect_left(D, R[i][0]+R[i][1]) - 1
S = SegTreeMax(A)

dp = [[0 for j in range(2)] for i in range(N)]
dp[N-1][0] = 1
dp[N-1][1] = 1
for i in range(N-1, 0, -1):
    dp[i-1][0] = (dp[i][0] + dp[i][1]) % MOD
    if A[i-1] != i-1:
        S.update(i-1,S.query(i-1, A[i-1]+1))
        dp[i-1][1] = (dp[S.query(i-1,i)][1])% MOD
    else:
        dp[i-1][1] = (dp[i][0] + dp[i][1]) % MOD
print((dp[0][0]+dp[0][1]) % MOD)

Submission status: Time Limit Exceeded

Solution code:
def i1():
 return int(input())
def i2():
 return [int(i) for i in input().split()]
import bisect
mod=998244353
n=i1()
d=[]
N=1<<(n.bit_length())
t=[-1 for i in range(2*N-1)]

def ud(i,x):
  i+=N-1
  t[i]=x
  while i:
    i=(i-1)//2
    t[i]=max(t[i*2+1],t[i*2+2]) 
     

def qr(a,b):
    a+=N-1
    b+=N-1
    L = -1
    R = -1
    while a < b:
      if a&1==0:
         L = max(L, t[a])
      if b&1==0:
         b-=1
         R = max(t[b], R)
      
      a>>=1
      b>>=1
      
         
    return max(L, R)
 
for i in range(n):
  d.append(i2())
d=sorted(d)
dx=[]
dd=[]
for i,j in d:
  dx.append(i)
  dd.append(j)

for i in range(n)[::-1]:
 j=bisect.bisect_left(dx,dx[i]+dd[i])
 tt=qr(i,j)
 ud(i,max(i,tt))
dp=[0 for i in range(n+1)]
dp[-1]=1
for i in range(n)[::-1]:
  dp[i]+=dp[i+1]
  dp[i]+=dp[t[i+N-1]+1]
  dp[i]%=mod
print(dp[0])

Submission status: Time Limit Exceeded

Solution code:
def i1():
 return int(input())
def i2():
 return [int(i) for i in input().split()]
import bisect
import sys
sys.setrecursionlimit(10**6)
mod=998244353
n=i1()
d=[]
N=1<<(n.bit_length())
t=[-1 for i in range(2*N-1)]

def ud(i,x):
  i+=N-1
  t[i]=x
  while i:
    i=(i-1)//2
    t[i]=max(t[i*2+1],t[i*2+2])

def qr(a,b,k,l,r):
  if r<=a or b<=l:
     return -1
  elif a<=l and r<=b:
     return t[k]
  else:
     return max(qr(a,b,k*2+1,l,(l+r)//2),qr(a,b,k*2+2,(l+r)//2,r))

for i in range(n):
  d.append(i2())
d=sorted(d)
dx=[]
dd=[]
for i,j in d:
  dx.append(i)
  dd.append(j)
r=[]
for i in range(n):
 j=bisect.bisect_left(dx,dx[i]+dd[i])-1
 r.append(j)

for i in range(n)[::-1]:
 tt=qr(i,r[i]+1,0,0,N)
 ud(i,max(r[i],tt))
dp=[0 for i in range(n+1)]
dp[-1]=1
for i in range(n)[::-1]:
  dp[i]+=dp[i+1]
  dp[i]%=mod
  dp[i]+=dp[t[i+N-1]+1]
  dp[i]%=mod
print(dp[0])

Submission status: Time Limit Exceeded

Solution code:
def i1():
 return int(input())
def i2():
 return [int(i) for i in input().split()]
import bisect
import sys
sys.setrecursionlimit(10**6)
mod=998244353
n=i1()
d=[]
N=1<<(n.bit_length())
t=[-1 for i in range(2*N-1)]

def ud(i,x):
  i+=N-1
  t[i]=x
  while i:
    i=(i-1)//2
    t[i]=max(t[i*2+1],t[i*2+2])

def qr(a,b,k,l,r):
  if r<=a or b<=l:
     return -1
  elif a<=l and r<=b:
     return t[k]
  else:
     return max(qr(a,b,k*2+1,l,(l+r)//2),qr(a,b,k*2+2,(l+r)//2,r))

for i in range(n):
  d.append(i2())
d=sorted(d)
dx=[]
dd=[]
for i,j in d:
  dx.append(i)
  dd.append(j)
r=[]
for i in range(n):
 j=bisect.bisect_left(dx,dx[i]+dd[i])-1
 r.append(j)
 ud(i,j)

for i in range(n)[::-1]:
 tt=qr(i,r[i]+1,0,0,N)
 ud(i,tt)
dp=[0 for i in range(n+1)]
dp[-1]=1
for i in range(n)[::-1]:
  dp[i]+=dp[i+1]
  dp[i]%=mod
  dp[i]+=dp[t[i+N-1]+1]
  dp[i]%=mod
print(dp[0])

Submission status: Time Limit Exceeded

Solution code:
def i1():
 return int(input())
def i2():
 return [int(i) for i in input().split()]
import bisect
import sys
import math
sys.setrecursionlimit(10**6)
mod=998244353
n=i1()
d=[]
N=1<<int(math.log2(n))
if int(math.log2(n))< math.log2(n):
   N<<=1
t=[-1 for i in range(2*N-1)]

def ud(i,x):
  i+=N-1
  t[i]=x
  while i:
    i=(i-1)//2
    t[i]=max(t[i*2+1],t[i*2+2])

def qr(a,b,k,l,r):
  if r<=a or b<=l:
     return -1
  elif a<=l and r<=b:
     return t[k]
  else:
     return max(qr(a,b,k*2+1,l,(l+r)//2),qr(a,b,k*2+2,(l+r)//2,r))

for i in range(n):
  d.append(i2())
d=sorted(d)
dx=[]
dd=[]
for i,j in d:
  dx.append(i)
  dd.append(j)
r=[]
for i in range(n):
 j=bisect.bisect_left(dx,dx[i]+dd[i])-1
 r.append(j)
 ud(i,j)

for i in range(n)[::-1]:
 tt=qr(i,r[i]+1,0,0,N)
 ud(i,tt)
dp=[0 for i in range(n+1)]
dp[-1]=1
for i in range(n)[::-1]:
  dp[i]+=dp[i+1]
  dp[i]%=mod
  dp[i]+=dp[t[i+N-1]+1]
  dp[i]%=mod
print(dp[0])

Submission status: Time Limit Exceeded

Solution code:
from bisect import bisect_left

class SegTree:
    def __init__(self, a):
        self.padding = -float('inf')
        self.n = len(a)
        self.N = 2 ** (self.n - 1).bit_length()
        self.data = [self.padding]*(self.N - 1) + a + [self.padding]*(self.N - self.n)
        for i in range(2 * self.N - 2, 0, -2):
            self.data[(i - 1) // 2] = max(self.data[i], self.data[i - 1])
    
    def __len__(self):
        return self.n
    
    def __getitem__(self, key):
        return self.data[self.N - 1 + key]

    def __setitem__(self, i, value):
        self._update(i, value)
    
    def _update(self, i, x):
        idx = self.N - 1 + i
        self.data[idx] = x
        while idx != 0:
            idx = (idx - 1) // 2
            self.data[idx] = max(self.data[2 * idx + 1], self.data[2 * idx + 2])
    
    def max(self, i, j):
        # [i, j)
        if i == j: #今回のみの措置
            return self.data[self.N - 1 + i]
        else:
            idx1 = self.N - 1 + i
            idx2 = self.N - 2 + j # 閉区間にする
            result = self.padding
            while idx1 + 1 < idx2:
                if idx1 % 2 == 0: # idx1が偶数
                    result = max(result, self.data[idx1])
                if idx2 % 2 == 1: # idx2が奇数
                    result = max(result, self.data[idx2])
                    idx2 -= 1
                
                idx1 //= 2
                idx2 = (idx2 - 1)//2
            
            if idx1 == idx2:
                result = max(result, self.data[idx1])
            else: # idx1 + 1 == idx2
                result = max(result, self.data[idx1], self.data[idx2])
            
            return result

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 = SegTree([t for t in shortright])
for i in range(n - 1, -1, -1):
    right[i] = right.max(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:
# -*- coding: utf-8 -*-

import sys
from bisect import bisect_left

def input(): return sys.stdin.readline().strip()
def list2d(a, b, c): return [[c] * b for i in range(a)]
def list3d(a, b, c, d): return [[[d] * c for j in range(b)] for i in range(a)]
def list4d(a, b, c, d, e): return [[[[e] * d for j in range(c)] for j in range(b)] for i in range(a)]
def ceil(x, y=1): return int(-(-x // y))
def INT(): return int(input())
def MAP(): return map(int, input().split())
def LIST(N=None): return list(MAP()) if N is None else [INT() for i in range(N)]
def Yes(): print('Yes')
def No(): print('No')
def YES(): print('YES')
def NO(): print('NO')
sys.setrecursionlimit(10 ** 9)
INF = 10 ** 18
MOD = 998244353

class SegTree:
    """
    セグメント木
    1.update:  i番目の値をxに更新する
    2.query: 区間[l, r)の値を得る
    """

    def __init__(self, n, func, intv, A=[]):
        """
        :param n: 要素数(0-indexed)
        :param func: 値の操作に使う関数(min, max, add, gcdなど)
        :param intv: 要素の初期値(単位元)
        :param A: 初期化に使うリスト(オプション)
        """
        self.n = n
        self.func = func
        self.intv = intv
        # nより大きい2の冪数
        n2 = 1
        while n2 < n:
            n2 <<= 1
        self.n2 = n2
        self.tree = [self.intv] * (n2 << 1)
        # 初期化の値が決まっている場合
        if A:
            # 1段目(最下段)の初期化
            for i in range(n):
                self.tree[n2+i] = A[i]
            # 2段目以降の初期化
            for i in range(n2-1, -1, -1):
                self.tree[i] = self.func(self.tree[i*2], self.tree[i*2+1])

    def update(self, i, x):
        """
        i番目の値をxに更新
        :param i: index(0-indexed)
        :param x: update value
        """
        i += self.n2
        self.tree[i] = x
        while i > 0:
            i >>= 1
            self.tree[i] = self.func(self.tree[i*2], self.tree[i*2+1])

    def query(self, a, b):
        """
        [a, b)の値を得る
        :param a: index(0-indexed)
        :param b: index(0-indexed)
        """
        l = a + self.n2
        r = b + self.n2
        s = self.intv
        while l < r:
            if r & 1:
                r -= 1
                s = self.func(s, self.tree[r])
            if l & 1:
                s = self.func(s, self.tree[l])
                l += 1
            l >>= 1
            r >>= 1
        return s

    def get(self, i):
        """ 一点取得 """
        return self.tree[i+self.n2]

    def all(self):
        """ 全区間[0, n)の取得 """
        return self.tree[1]

    def print(self):
        for i in range(self.n):
            print(self.get(i), end=' ')
        print()

N = INT()
XD = []
for _ in range(N):
    x, d = MAP()
    XD.append((x, d))

XD.sort()
X, _ = zip(*XD)
X = list(X)
X += [INF]
# st[i] := ロボットiが動くことで、何番目のロボットまで連動して動くか
st = SegTree(N+1, max, -INF)
st.update(N, N)
for i in range(N-1, -1, -1):
    x, d = XD[i]
    j = bisect_left(X, x+d)
    mx = st.query(i, j)
    st.update(i, max(i, mx))

# dp[i] := i番目のロボットまで(後ろから)見て、そこから後ろの状態の通り数
dp = [0] * (N+1)
dp[N] = 1
for i in range(N-1, -1, -1):
    # i番目を動かさない遷移(1つ前の状態全てを使える)
    dp[i] += dp[i+1]
    # i番目を動かす遷移(自分が影響する範囲は自由に変えられないので、その1つ前から持ってくる)
    dp[i] += dp[st.get(i)+1]
ans = dp[0] % MOD
print(ans)

Submission status: Time Limit Exceeded

Solution code:
import sys
import bisect
input = sys.stdin.readline

class SegmentTree:
    def __init__(self, a):
        self.padding = -float('inf')
        self.n = len(a)
        self.N = 2 ** (self.n-1).bit_length()
        self.data = [self.padding]*(self.N-1) + a + [self.padding]*(self.N-self.n)
        for i in range(2*self.N-2, 0, -2):
            self.data[(i-1)//2] = max([self.data[i], self.data[i-1]])
    
    def __len__(self):
        return self.n
    
    def update(self, i, x):
        idx = self.N - 1 + i
        self.data[idx] = x
        while idx:
            idx = (idx-1) // 2
            self.data[idx] = max([self.data[2*idx+1], self.data[2*idx+2]])
    
    def query(self, i, j):
        # [i, j)
        if i == j:
            return self.data[self.N - 1 + i]
        else:
            idx1 = self.N - 1 + i
            idx2 = self.N - 2 + j # 閉区間にする
            result = self.padding
            while idx1 + 1 < idx2:
                if idx1&1 == 0: # idx1が偶数
                    result = max([result, self.data[idx1]])
                if idx2&1 == 1: # idx2が奇数
                    result = max([result, self.data[idx2]])
                    idx2 -= 1
                
                idx1 //= 2
                idx2 = (idx2 - 1)//2
            
            if idx1 == idx2:
                result = max([result, self.data[idx1]])
            else: # idx1 + 1 == idx2
                result = max([result, self.data[idx1], self.data[idx2]])
            
            return result


MOD = 998244353
N = int(input())
XD = [list(map(int, input().split())) for i in range(N)]
XD.sort()

X = [xd[0] for xd in XD]

dp = [0]*N + [1]
touch_range = [i for i in range(N)]
st = SegmentTree(touch_range)
for i in range(N-1, -1, -1):
  right = X[i] + XD[i][1]
  idx = bisect.bisect_left(X, right)-1
  if idx > i:
    idx = st.query(i, idx+1)
    st.update(i, idx) 
  dp[i] = (dp[i+1] + dp[idx+1]) % MOD

print(dp[0])

Submission status: Time Limit Exceeded

Solution code:
import sys
import bisect
input = sys.stdin.readline

class SegmentTree:
    def __init__(self, a):
        self.padding = -float('inf')
        self.n = len(a)
        self.N = 2 ** (self.n-1).bit_length()
        self.data = [self.padding]*(self.N-1) + a + [self.padding]*(self.N-self.n)
        for i in range(2*self.N-2, 0, -2):
            self.data[(i-1)//2] = max([self.data[i], self.data[i-1]])
    
    def __len__(self):
        return self.n
    
    def update(self, i, x):
        idx = self.N - 1 + i
        self.data[idx] = x
        while idx:
            idx = (idx-1) // 2
            self.data[idx] = max([self.data[2*idx+1], self.data[2*idx+2]])
    
    def query(self, i, j):
        # [i, j)
        if i == j:
            return self.data[self.N - 1 + i]
        else:
            idx1 = self.N - 1 + i
            idx2 = self.N - 2 + j # 閉区間にする
            result = self.padding
            while idx1 + 1 < idx2:
                if idx1&1 == 0: # idx1が偶数
                    result = max([result, self.data[idx1]])
                if idx2&1 == 1: # idx2が奇数
                    result = max([result, self.data[idx2]])
                    idx2 -= 1
                
                idx1 //= 2
                idx2 = (idx2 - 1)//2
            
            if idx1 == idx2:
                result = max([result, self.data[idx1]])
            else: # idx1 + 1 == idx2
                result = max([result, self.data[idx1], self.data[idx2]])
            
            return result


MOD = 998244353
N = int(input())
XD = [list(map(int, input().split())) for i in range(N)]
XD.sort()

X = [xd[0] for xd in XD]
D = [xd[1] for xd in XD]

dp = [0]*N + [1]
touch_range = [i for i in range(N)]
st = SegmentTree(touch_range)
for i in range(N-1, -1, -1):
  right = X[i] + D[i]
  idx = bisect.bisect_left(X, right)
  if idx > i:
    idx = st.query(i, idx)
    st.update(i, idx) 
  dp[i] = (dp[i+1] + dp[idx+1]) % MOD

print(dp[0])

Submission status: Time Limit Exceeded

Solution code:
import sys
import bisect
input = sys.stdin.readline

class SegmentTree:
    def __init__(self, a):
        self.padding = -float('inf')
        self.n = len(a)
        self.N = 2 ** (self.n-1).bit_length()
        self.data = [self.padding]*(self.N-1) + a + [self.padding]*(self.N-self.n)
        for i in range(2*self.N-2, 0, -2):
            self.data[(i-1)//2] = max([self.data[i], self.data[i-1]])
    
    def __len__(self):
        return self.n
    
    def update(self, i, x):
        idx = self.N - 1 + i
        self.data[idx] = x
        while idx:
            idx = (idx-1) // 2
            self.data[idx] = max([self.data[2*idx+1], self.data[2*idx+2]])
    
    def query(self, i, j):
        # [i, j)
        if i == j:
            return self.data[self.N - 1 + i]
        else:
            idx1 = self.N - 1 + i
            idx2 = self.N - 2 + j # 閉区間にする
            result = self.padding
            while idx1 + 1 < idx2:
                if idx1&1 == 0: # idx1が偶数
                    result = max([result, self.data[idx1]])
                if idx2&1 == 1: # idx2が奇数
                    result = max([result, self.data[idx2]])
                    idx2 -= 1
                
                idx1 //= 2
                idx2 = (idx2 - 1)//2
            
            if idx1 == idx2:
                result = max([result, self.data[idx1]])
            else: # idx1 + 1 == idx2
                result = max([result, self.data[idx1], self.data[idx2]])
            
            return result


MOD = 998244353
N = int(input())
XD = [list(map(int, input().split())) for i in range(N)]
XD.sort()

X = [xd[0] for xd in XD]
D = [xd[1] for xd in XD]

dp = [0]*N + [1]
touch_range = [i for i in range(N)]
st = SegmentTree(touch_range)
for i in range(N-1, -1, -1):
  right = X[i] + D[i]
  idx = bisect.bisect_left(X, right)
  r = st.query(i, idx)
  st.update(i, r)
  dp[i] = (dp[i+1] + dp[r+1]) % MOD


print(dp[0])

Submission status: Time Limit Exceeded

Solution code:
import sys
import bisect
input = sys.stdin.readline

class SegmentTree:
    def __init__(self, a):
        self.padding = -float('inf')
        self.n = len(a)
        self.N = 2 ** (self.n-1).bit_length()
        self.data = [self.padding]*(self.N-1) + a + [self.padding]*(self.N-self.n)
        for i in range(2*self.N-2, 0, -2):
            self.data[(i-1)//2] = max([self.data[i], self.data[i-1]])
    
    def __len__(self):
        return self.n
    
    def update(self, i, x):
        idx = self.N - 1 + i
        self.data[idx] = x
        while idx:
            idx = (idx-1) // 2
            self.data[idx] = max([self.data[2*idx+1], self.data[2*idx+2]])
    
    def query(self, i, j):
        # [i, j)
        if i == j:
            return self.data[self.N - 1 + i]
        else:
            idx1 = self.N - 1 + i
            idx2 = self.N - 2 + j # 閉区間にする
            result = self.padding
            while idx1 + 1 < idx2:
                if idx1&1 == 0: # idx1が偶数
                    result = max([result, self.data[idx1]])
                if idx2&1 == 1: # idx2が奇数
                    result = max([result, self.data[idx2]])
                    idx2 -= 1
                
                idx1 //= 2
                idx2 = (idx2 - 1)//2
            
            if idx1 == idx2:
                result = max([result, self.data[idx1]])
            else: # idx1 + 1 == idx2
                result = max([result, self.data[idx1], self.data[idx2]])
            
            return result


MOD = 998244353
N = int(input())
XD = [list(map(int, input().split())) for i in range(N)]
XD.sort()

X = [xd[0] for xd in XD]
D = [xd[1] for xd in XD]

touch_range = [i for i in range(N)]
st = SegmentTree(touch_range)
for i in range(N-2, -1, -1):
  right = X[i] + D[i]
  idx = bisect.bisect_left(X, right)
  r = st.query(i, idx)
  st.update(i, r)
  touch_range[i] = r

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

print(dp[0])

Submission status: Time Limit Exceeded

Solution code:
import bisect

class SegmentTree:
    def __init__(self, a, mode='min'):
        if mode == 'min':
            self.padding = float('inf')
            self.func = min
        elif mode == 'max':
            self.padding = -float('inf')
            self.func = max
        elif mode == 'sum':
            self.padding = 0
            self.func = sum
        
        self.n = len(a)
        self.N = 2 ** (self.n-1).bit_length()
        self.data = [self.padding]*(self.N-1) + a + [self.padding]*(self.N-self.n)
        for i in range(2*self.N-2, 0, -2):
            self.data[(i-1)//2] = self.func([self.data[i], self.data[i-1]])
    
    def __len__(self):
        return self.n
    
    def update(self, i, x):
        idx = self.N - 1 + i
        self.data[idx] = x
        while idx:
            idx = (idx-1) // 2
            self.data[idx] = self.func([self.data[2*idx+1], self.data[2*idx+2]])
    
    def query(self, i, j):
        # [i, j)
        if i == j:
            return self.data[self.N - 1 + i]
        else:
            idx1 = self.N - 1 + i
            idx2 = self.N - 2 + j # 閉区間にする
            result = self.padding
            while idx1 + 1 < idx2:
                if idx1&1 == 0: # idx1が偶数
                    result = self.func([result, self.data[idx1]])
                if idx2&1 == 1: # idx2が奇数
                    result = self.func([result, self.data[idx2]])
                    idx2 -= 1
                
                idx1 //= 2
                idx2 = (idx2 - 1)//2
            
            if idx1 == idx2:
                result = self.func([result, self.data[idx1]])
            else: # idx1 + 1 == idx2
                result = self.func([result, self.data[idx1], self.data[idx2]])
            
            return result


MOD = 998244353
N = int(input())
XD = [list(map(int, input().split())) for i in range(N)]
XD.sort()

X = [xd[0] for xd in XD]
D = [xd[1] for xd in XD]

touch_range = [i for i in range(N)]
st = SegmentTree(touch_range, mode='max')
for i in range(N-2, -1, -1):
  right = X[i] + D[i]
  idx = bisect.bisect_left(X, right)
  r = st.query(i, idx)
  st.update(i, r)
  touch_range[i] = r

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

print(dp[0])

Submission status: Time Limit Exceeded

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

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)]

parent = [-1] * N

MAXIDX = 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, min(idx, MAXIDX)):
        if parent[j] < 0:
            parent[j] = i
    if idx >= MAXIDX:
        MAXIDX = i + 1

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)