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 .

Solution (Python):
class SegTree:
    X_unit = -10**10
    X_f = max

    def __init__(self, N):
        self.N = N
        self.X = [self.X_unit] * (N + N)

    def build(self, seq):
        for i, x in enumerate(seq, self.N):
            self.X[i] = x
        for i in range(self.N - 1, 0, -1):
            self.X[i] = self.X_f(self.X[i << 1], self.X[i << 1 | 1])

    def set_val(self, i, x):
        i += self.N
        self.X[i] = x
        while i > 1:
            i >>= 1
            self.X[i] = self.X_f(self.X[i << 1], self.X[i << 1 | 1])

    def fold(self, L, R):
        L += self.N
        R += self.N
        vL = self.X_unit
        vR = self.X_unit
        while L < R:
            if L & 1:
                vL = self.X_f(vL, self.X[L])
                L += 1
            if R & 1:
                R -= 1
                vR = self.X_f(self.X[R], vR)
            L >>= 1
            R >>= 1
        return self.X_f(vL, vR)

from bisect import bisect_left
mod = 998244353
N = int(input())
robots = []
for i in range(N):
    Xi,Di = map(int,input().split())
    robots.append((Xi,Di))
robots.sort(key=lambda x:x[0])
X = [rob[0] for rob in robots]
D = [rob[1] for rob in robots]

ST = SegTree(N)
ST.set_val(N-1,N-1)
for i in range(N-1)[::-1]:
    r = bisect_left(X,X[i]+D[i])
    if i+1 == r:
        ST.set_val(i,i)
    else:
        ST.set_val(i,ST.fold(i+1,r))
to = ST.X[N:]
dp = [0]*(N+1)
dp[0] = 1
for i in range(N):
    dp[to[i]+1] += dp[i]
    dp[to[i]+1] %= mod
    dp[i+1] += dp[i]
    dp[i+1] %= mod
print(dp[N])

Solution (Python):
import sys
import numpy as np
import numba
from numba import njit
from numba.types import Omitted
i4 = numba.int32
i8 = numba.int64

read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
readlines = sys.stdin.buffer.readlines

MOD = 998_244_353

@njit((numba.types.optional(i8), ) * 2, cache=True)
def seg_f(x, y):
    if x is None:
        return y
    if y is None:
        return x
    return max(x, y)


@njit((i8[:], ), cache=True)
def build(raw_data):
    N = len(raw_data)
    seg = np.zeros(N + N, np.int64)
    seg[N:] = raw_data
    for i in range(N - 1, 0, -1):
        seg[i] = seg_f(seg[i << 1], seg[i << 1 | 1])
    return seg


@njit((i8[:], i8, i8), cache=True)
def set_val(seg, i, x):
    N = len(seg) // 2
    i += N
    seg[i] = x
    while i > 1:
        i >>= 1
        seg[i] = seg_f(seg[i << 1], seg[i << 1 | 1])


@njit((i8[:], i8, i8), cache=True)
def fold(seg, l, r):
    vl = vr = None
    N = len(seg) // 2
    l, r = l + N, r + N
    while l < r:
        if l & 1:
            vl = seg_f(vl, seg[l])
            l += 1
        if r & 1:
            r -= 1
            vr = seg_f(seg[r], vr)
        l, r = l >> 1, r >> 1
    return seg_f(vl, vr)

def main(XD):
    X, D = XD[::2], XD[1::2]
    N = len(X)
    argsort = np.argsort(X)
    X, D = X[argsort], D[argsort]
    INF = 1 << 60
    X = np.append(X, INF)
    D = np.append(D, 1)
    
    dp0 = np.searchsorted(X, X + D)
    seg = build(dp0)
    for n in range(N - 1, -1, -1):
        x = fold(seg, n, dp0[n])
        dp0[n] = x
        set_val(seg, n, x)
    
    dp = np.zeros(N + 1, np.int64)
    dp[-1] = 1
    for n in range(N - 1, -1, -1):
        nxt = dp0[n]
        dp[n] = (dp[n + 1] + dp[nxt]) % MOD  
    return dp[0]

N = int(readline())
XD = np.array(read().split(), np.int64)

print(main(XD))

Solution (Python):
n=int(input())
xd=[list(map(int,input().split())) for _ in range(n)]
xd.sort(key=lambda x:x[0])
aryx=[x for x,d in xd]
mod=998244353
dp=[1]*(n+1)

r=list(range(n))
r[n-1]=n-1
from bisect import bisect_left

class SegmentTree:
    
    
    
    def __init__(self, size, f=lambda x,y : max(x,y), default=0):
        self.size = 2**(size-1).bit_length() 
        self.default = default
        self.dat = [default]*(self.size*2) 
        self.f = f

    def update(self, i, x):
        i += self.size
        self.dat[i] = x
        while i > 0:
            i >>= 1
            self.dat[i] = self.f(self.dat[i*2], self.dat[i*2+1])

    def query(self, l, r):
        l += self.size
        r += self.size
        lres, rres = self.default, self.default
        while l < r:
            if l & 1:
                lres = self.f(lres, self.dat[l])
                l += 1

            if r & 1:
                r -= 1
                rres = self.f(self.dat[r], rres) 
            l >>= 1
            r >>= 1
        res = self.f(lres, rres)
        return res
st=SegmentTree(n)
for i in range(n):
    st.update(i,i)

for i in range(n):
    x,d=xd[n-1-i]
    tmp=bisect_left(aryx,x+d)
    sti=st.query(n-1-i,tmp)
    st.update(n-1-i,sti)
    dp[n-1-i]=dp[n-1-i+1]+dp[sti+1]
    dp[n-1-i]%=mod
print(dp[0])

Solution (Python):
def numba_compile(numba_config):
    import os, sys
    if sys.argv[-1] == "ONLINE_JUDGE":
        from numba import njit
        from numba.pycc import CC
        cc = CC("my_module")
        for func, signature in numba_config:
            globals()[func.__name__] = njit(signature)(func)
            cc.export(func.__name__, signature)(func)
        cc.compile()
        exit()
    elif os.name == "posix":
        exec(f"from my_module import {','.join(func.__name__ for func, _ in numba_config)}")
        for func, _ in numba_config:
            globals()[func.__name__] = vars()[func.__name__]
    else:
        from numba import njit
        for func, signature in numba_config:
            globals()[func.__name__] = njit(signature, cache=True)(func)
        print("compiled!", file=sys.stderr)


import sys
from bisect import bisect_left
from operator import itemgetter


import numpy as np

def segment_tree_op(a, b):
    return a if a[0] > b[0] else b

def segment_tree_get(seg, l, r):
    elem_size, tree, result, _ = seg
    l += elem_size
    r += elem_size
    while l < r:
        if l & 1:
            result = segment_tree_op(tree[l], result)
            l += 1
        if r & 1:
            r -= 1
            result = segment_tree_op(tree[r], result)
        l, r = l >> 1, r >> 1
    return result

def segment_tree_set(seg, i, value):
    elem_size, tree, _, _ = seg
    k = elem_size + i
    tree[k] = value
    while k > 1:
        k >>= 1
        tree[k] = segment_tree_op(tree[k<<1], tree[k<<1|1])

def segment_tree_get_one(seg, i):
    elem_size, tree, _, _ = seg
    return tree[i+elem_size]

def segment_tree_construct(arr):
    identity = np.array([0], dtype=np.int64)
    real_size = len(arr)
    elem_size = 1 << int(np.log2(real_size-1))+1
    tree = np.empty((elem_size*2, len(identity)), dtype=np.int64)
    tree[elem_size:elem_size+real_size] = arr
    tree[elem_size+real_size:] = identity
    for i in range(elem_size - 1, 0, -1):
        tree[i] = segment_tree_op(tree[i<<1], tree[i<<1|1])
    return elem_size, tree, identity, real_size

class SegmentTree:
    element_type = "i8[:]"
    a_type = f"Tuple((i8,i8[:,:],{element_type},i8))"
    numba_config = [
        [segment_tree_op, f"{element_type}({element_type},{element_type})"],
        [segment_tree_construct, f"{a_type}(i8[:,:])"],
        [segment_tree_get, f"{element_type}({a_type},i8,i8)"],
        [segment_tree_set, f"void({a_type},i8,{element_type})"],
        [segment_tree_get_one, f"{element_type}({a_type},i8)"],
    ]
    def __init__(self, arr):
        self.a = segment_tree_construct(arr)

    def get(self, l, r):
        return segment_tree_get(self.a, l, r)

    def set(self, i, value):
        return segment_tree_set(self.a, i, value)

    def get_one(self, i):
        return segment_tree_get_one(self.a, i)

numba_compile(SegmentTree.numba_config)

def main():
    mod = 998244353
    N = int(sys.stdin.buffer.readline())
    m = map(int, sys.stdin.buffer.read().split())
    XD = list(zip(m, m))
    XD.sort(key=itemgetter(0))
    X, D = zip(*XD)
    seg = SegmentTree(np.arange(N, dtype=np.int64).reshape(N, 1))
    for i, (x, d) in zip(range(N-1,-1,-1), XD[::-1]):
        r = bisect_left(X, x+d, lo=i)
        seg.set(i, seg.get(i, r))
    D2 = seg.a[1][seg.a[0]:seg.a[0]+seg.a[3]].ravel()
    Q = [0] * N
    ans = 1
    cnt = 1
    for i, d in enumerate(D2):
        ans += cnt
        Q[d] += cnt
        cnt = (cnt + Q[i]) % mod
    print(ans % mod)

main()

Solution (Python):
from heapq import *
N=int(input())
X=[list(map(int,input().split())) for i in range(N)]
X.sort(reverse=True)
Q=[]
heapify(Q)
Y=0
mod=998244353
for i in range(N):
  Y=1
  while len(Q):
    if Q[0][0]<X[i][0]+X[i][1]:
      Y=Y*Q[0][1]%mod
      heappop(Q)
    else:
      break
  heappush(Q,(X[i][0],Y+1))
P=1
while len(Q):
  P=P*heappop(Q)[1]%mod
print(P)

Solution (Python):
def examA():
    S = SI()
    if S=="AAA" or S=="BBB":
        print("No")
    else:
        print("Yes")
    return

def examB():
    N, A, B = LI()
    loop = N//(A+B)
    ans = loop*A + min(A,N%(A+B))
    print(ans)
    return

def examC():
    A, B = LI()
    ans = -1
    for i in range(1,20000):
        if i*8//100==A:
            if i*10//100==B:
                ans = i
                break
    print(ans)
    return

def examD():
    S = SI()
    Q = I()
    rev = 0
    L = ""; R = ""
    for _ in range(Q):
        q = LSI()
        if q[0]=="1":
            rev += 1
        else:
            c = int(q[1])
            if (c+rev)%2==1:
                L += q[2]
            else:
                R += q[2]
    ans = ""
    if rev%2==0:
        ans = L[::-1] + S + R
    else:
        ans = R[::-1] + S[::-1] + L
    print(ans)
    return

def examE():
    N, P = LI()
    S = SI()
    A = [0]*(N+1)
    cur = 0
    if P==5:
        ans = 0
        for i in range(N):
            if int(S[N-1-i])%5==0:
                ans += N-i
        print(ans)
        return
    elif P==2:
        ans = 0
        for i in range(N):
            if int(S[N-1-i])%2==0:
                ans += N-i
        print(ans)
        return

    for i in range(N):
        s = int(S[N-1-i])
        cur += s*pow(10,i,P)
        A[i+1] = cur%P
    D = [0]*P
    for a in A:
        D[a] += 1
    ans = 0
    
    for d in D:
        ans += d*(d-1)//2

    print(ans)
    return

def examF():
    def dfs(n, s):
        
        
        cur = 1
        can = sum(X[s])
        for i in range(s,n):
            if X[i][0]>=can:
                V[s] = cur
                return cur, i
            if i==n-1:
                return cur,i
            now, visited = dfs(n, i+1)
            cur += now
        V[s] = cur
        return cur, n
    N = I()
    X = [LI()for _ in range(N)]
    X.sort()
    V = [[]for _ in range(N)]
    neg = 0
    ans = dfs(N,0)
    print(V)

    print(ans)
    return

def examF2():
    N = I()
    X = [LI()for _ in range(N)]
    N += 1
    X.sort()
    parent = [-1] * N
    

    stack = [(inf,-1)]
    for i,(x,d) in enumerate(X):
        d += x
        
        
        while(stack[-1][0]<=x):
            stack.pop()
        parent[i] = stack[-1][1]
        stack.append((d,i))

    
    dp = [1]*N
    ans = 1
    for i in range(N-1)[::-1]:
        p = parent[i]
        if p==-1:
            ans *= dp[i]+1
            ans %= mod2
            continue
        dp[p] *= dp[i]+1
        dp[p] %= mod2

    print(ans)
    return

import sys,copy,bisect,itertools,heapq,math,random
from heapq import heappop,heappush,heapify
from collections import Counter,defaultdict,deque
def I(): return int(sys.stdin.readline())
def LI(): return list(map(int,sys.stdin.readline().split()))
def LSI(): return list(map(str,sys.stdin.readline().split()))
def LS(): return sys.stdin.readline().split()
def SI(): return sys.stdin.readline().strip()
global mod,mod2,inf,alphabet,_ep
mod = 10**9 + 7
mod2 = 998244353
inf = 10**18
_ep = 10**(-12)
alphabet = [chr(ord('a') + i) for i in range(26)]

sys.setrecursionlimit(10**6)

if __name__ == '__main__':
    examF2()

"""

"""

Solution (Python):
import bisect

LI = lambda: list(map(int, input().split()))

N = int(input())
XD = [LI() for _ in range(N)]

MOD = 998244353


class BIT:

    def __init__(self, n):
        self.n = n
        self.dat = [i - 1 for i in range(self.n + 1)]

    def change(self, i, x):
        i += 1
        while i <= self.n:
            self.dat[i] = max(self.dat[i], x)
            i += i & -i

    def max_num(self, i):
        if i == 0:
            return -1
        return max(self.dat[i], self.max_num(i - (i & -i)))


def main():
    XD.sort()
    x = [None] * N
    d = [None] * N
    for i in range(N):
        x[i], d[i] = XD[i]
    
    bit = BIT(N)
    w = [None] * N
    for i in range(N - 1, -1, -1):
        v = x[i] + d[i]
        j = bit.max_num(bisect.bisect_left(x, v))
        w[i] = j - i
        bit.change(i, j)
    
    dp = [None] * (N + 1)
    dp[-1] = 1
    for i in range(N - 1, -1, -1):
        dp[i] = (dp[i + 1] + dp[i + w[i] + 1]) % MOD
    
    ans = dp[0]
    print(ans)


if __name__ == "__main__":
    main()

Solution (Python):
import sys
import bisect
input = sys.stdin.buffer.readline
sys.setrecursionlimit(10 ** 7)
inf = 10**18
mod = 998244353


class SegmentTree:
    def __init__(self, N, arr=None, op=None, unit=None):
        """
        INPUT
        N: 配列のサイズ
        segment tree: 1-indexedで構築
        original array: 0-indexed
                 1
           2           3
         4    5     6     7
        8 9 10 11 12 13 14 15
        ---------------------
        0 1 2  3  4  5  6  7
        """
        self.N = N
        self.unit = unit
        self.op = op
        self.tree = [unit] * (2 * N + 1)
        if arr is not None:
            self._build(arr)

    def _build(self, arr):
        op = self.op
        N = self.N
        for i, a in enumerate(arr, N):
            self.tree[i] = a
        for i in reversed(range(1, N)):
            self.tree[i] = op(self.tree[i << 1], self.tree[i << 1 | 1])

    def update(self, i, x):
        """
        arr[i]の値をxに変更する
        i: 0-indexed
        """
        i += self.N
        op = self.op
        self.tree[i] = x
        while i > 1:
            i >>= 1
            self.tree[i] = op(self.tree[i << 1], self.tree[i << 1 | 1])

    def val(self, i):
        return self.tree[i + self.N]

    def query(self, L, R):
        """
        L,R: 0-indexed
        半開区間[L,R)の累積演算した値を返す
        """
        op = self.op
        res = self.unit
        L += self.N
        R += self.N
        while L < R:
            if L & 1:
                res = op(res, self.tree[L])
                L += 1
            if R & 1:
                R -= 1
                res = op(res, self.tree[R])
            L >>= 1
            R >>= 1
        return res


N = int(input())
XD = list(tuple(map(int, input().split())) for _ in range(N))
XD.sort()
X, D = zip(*XD)
X += (inf, )


seg = SegmentTree(N+1, None, max, 0)
for L in reversed(range(N)):
    R = bisect.bisect_left(X, X[L] + D[L])
    p = seg.query(L, R)
    seg.update(L, max(L, p))

dp = [0] * (N + 1)
dp[-1] = 1
for i in reversed(range(N)):
    p = seg.val(i)
    dp[i] = (dp[i + 1] + dp[p + 1]) % mod

print(dp[0])

Solution (Python):
import sys
input = sys.stdin.readline

def I(): return int(input())
def MI(): return map(int, input().split())
def LI(): return list(map(int, input().split()))

def main():
    class SegTree:
        def __init__(self,N,ide,segfunc=min):
            self.ide_ele = ide
            """
            ex)
             最小値のセグ木 → +inf
              和のセグ木 → 0
              積のセグ木 → 1
              gcdのセグ木 → 0
            """
            
            self.segfunc=segfunc
            
            
            self.num =2**(N-1).bit_length()
            self.seg=[self.ide_ele]*2*self.num

        
        def setL(self,init_val):
            
            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
            while k:
                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

    mod=998244353
    N=I()
    X=[0]*N
    D=[0]*N
    
    for i in range(N):
        X[i],D[i]=MI()
    
    X,D=zip(*sorted(zip(X,D)))
    
    dp=[0]*(N+1)
    """
    dp[i]はi番目まで見たときと通り数，後ろから見てく．
    i番目を動かさないならば，dp[i+1]
    i番目を動かすならば，連鎖していき，影響が出ないところまで見る
    この連鎖分をセグ木で事前計算しておく．
    """
    seg=SegTree(N,0,max)
    seg.setL(range(N))
    
    
    import bisect 
    
    for i in range(N-1,-1,-1):
        t=X[i]+D[i]
        num=bisect.bisect_left(X,t)
        l=i
        r=num
        M=seg.query(l,r)
        seg.update(i,M)
        
    dp[-1]=1
    for i in range(N-1,-1,-1):
        temp=seg.query(i,i+1)
        dp[i]=(dp[i+1]+dp[temp+1])%mod
        
    print(dp[0])
    
    
    
        

main()

Solution (Python):
import bisect
import sys


sys.setrecursionlimit(10**6)
INF = 10**6


class SegTree:

    def __init__(self, N):
        self.N = N
        self.data = [- INF] * (2 * N - 1)

    def update(self, i, x):
        n = self.N + i - 1
        self.data[n] = x
        while n > 0:
            n = (n - 1) // 2
            self.data[n] = max(self.data[2 * n + 1], self.data[2 * n + 2])        

    def elem(self, i):
        return self.data[self.N + i - 1]

    def _query(self, a, b, k, l, r):
        if r <= a or b <= l:
            return - INF
        if a <= l and r <= b:
            return self.data[k]
        val_left = self._query(a, b, 2 * k + 1, l, (l + r) // 2)
        val_right = self._query(a, b, 2 * k + 2, (l + r) // 2, r)
        return max(val_left, val_right)

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


def main():
    MOD = 998244353
    N = int(input())
    robot_list = [list(map(int, input().split())) for _ in range(N)]
    robot_list.sort()  
    X = [robot[0] for robot in robot_list]
    D = [robot[1] for robot in robot_list]

    PW_N = 1
    while PW_N < N:
        PW_N *= 2
    next_robot_tree = SegTree(PW_N)
    next_robot_tree.update(N - 1, N)
    for n in range(N - 2, - 1, - 1):
        if X[n] + D[n] <= X[n + 1]:
            next_robot_tree.update(n, n + 1)
        else:
            next_robot = bisect.bisect_left(X, X[n] + D[n])
            next_robot = next_robot_tree.query(n, next_robot)
            next_robot_tree.update(n, next_robot)

    cnt = [0] * (N + 1)
    cnt[0] = 1
    for n in range(N):
        cnt[n + 1] += cnt[n]
        cnt[n + 1] %= MOD
        next_robot = next_robot_tree.elem(n)
        cnt[next_robot] += cnt[n]
        cnt[next_robot] %= MOD
    print(cnt[N])


if __name__ == '__main__':
    main()

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

MOD = 998244353

def init(G, robots, fs, p):
    q = p
    while q < len(robots) and robots[q][0] < robots[p][0] + robots[p][1]:
        if fs[q]:
            G[p].append(q)
            fs[q] = False
            q = init(G, robots, fs, q) - 1
        q += 1
    return q

def calc(G, p, fs):
    fs[p] = False
    if len(G[p]) == 0:
        return 2
    tmp = 1
    for v in G[p]:
        tmp *= calc(G, v, fs)
        tmp %= MOD
    tmp += 1
    return tmp

def main():
    n = int(input())
    robots = [list(map(int, input().split())) for _ in range(n)]
    G = [[] for _ in range(n)]
    robots.sort(key=lambda x: x[0])
    fs = [True]*n
    q = 0
    while q < n:
        if fs[q]:
            fs[q] = False
            init(G, robots, fs, q)
        else:
            q += 1
    fs = [True]*n
    ans = 1
    for i in range(n):
        if fs[i]:
            ans *= calc(G, i, fs)
            ans %= MOD
    print(ans % MOD)

if __name__ == "__main__":
    main()

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

MOD = 998244353

def init(G, robots, fs, p):
    q = p
    while q < len(robots) and robots[q][0] < robots[p][0] + robots[p][1]:
        if fs[q]:
            G[p].append(q)
            fs[q] = False
            q = init(G, robots, fs, q) - 1
        q += 1
    return q

def calc(G, p, fs):
    fs[p] = False
    if len(G[p]) == 0:
        return 2
    tmp = 1
    for v in G[p]:
        tmp *= calc(G, v, fs)
        tmp %= MOD
    tmp += 1
    return tmp

def main():
    n = int(input())
    robots = [list(map(int, input().split())) for _ in range(n)]
    G = [[] for _ in range(n)]
    robots.sort(key=lambda x: x[0])
    fs = [True]*n
    q = 0
    while q < n:
        if fs[q]:
            fs[q] = False
            init(G, robots, fs, q)
        else:
            q += 1
    fs = [True]*n
    ans = 1
    for i in range(n):
        if fs[i]:
            ans *= calc(G, i, fs)
            ans %= MOD
    print(ans % MOD)

if __name__ == "__main__":
    main()

Solution (Python):

import sys
from bisect import bisect_left,bisect_right
sys.setrecursionlimit(10**9)
INF=10**18
MOD=998244353
input=lambda: sys.stdin.readline().rstrip()
YesNo=lambda b: bool([print('Yes')] if b else print('No'))
YESNO=lambda b: bool([print('YES')] if b else print('NO'))
int1=lambda x:int(x)-1

N=int(input())
XD=[]
for i in range(N):
    XD.append(tuple(map(int,input().split())))
XD.sort(key=lambda t: t[0])
X,D=[0]*N,[0]*N
for i in range(N):
    X[i],D[i]=XD[i]

class SegmentTree:
    def __init__(self,n,segfunc,ide_ele):
        self.segfunc=segfunc
        self.ide_ele=ide_ele
        self.num=2**(n-1).bit_length()
        self.dat=[ide_ele]*2*self.num
    
    def init(self,iter):
        for i in range(len(iter)):
            self.dat[i+self.num]=iter[i]
        for i in range(self.num-1,0,-1):
            self.dat[i]=self.segfunc(self.dat[i*2],self.dat[i*2+1])
    
    def update(self,k,x):
        k+=self.num
        self.dat[k]=x
        while k:
            k//=2
            self.dat[k]=self.segfunc(self.dat[k*2],self.dat[k*2+1])
    
    def query(self,p,q):
        if q<=p:
            return self.ide_ele
        p+=self.num
        q+=self.num-1
        res=self.ide_ele
        while q-p>1:
            if p&1==1:
                res=self.segfunc(res,self.dat[p])
            if q&1==0:
                res=self.segfunc(res,self.dat[q])
                q-=1
            p=(p+1)//2
            q=q//2
        if p==q:
            res=self.segfunc(res,self.dat[p])
        else:
            res=self.segfunc(self.segfunc(res,self.dat[p]),self.dat[q])
        return res

edge=[0]*N
s=SegmentTree(N,lambda a,b: max(a,b),0)
s.init([i for i in range(N)])
for i in range(N-1,-1,-1):
    res0=bisect_left(X,X[i]+D[i])
    res=s.query(i,res0)
    edge[i]=res
    s.update(i,res)
dp=[0]*(N+1)
dp[-1]=1
for i in range(N-1,-1,-1):
    dp[i]+=dp[i+1]+dp[edge[i]+1]
    dp[i]%=MOD
print(dp[0])

Solution (Python):
import numpy as np
import collections

Robot = collections.namedtuple('Robot', ['l', 'r'])

N = int(input())
MOD = 998244353
robots = []
for _ in range(N):
    x, d = map(int, input().split())
    robots.append(Robot(x, x + d))
robots.sort()

robots.append(Robot(10**10, 10**10 + 1))
stack = [N]

dp = np.zeros(N + 1, dtype=int)
dp[N] = 1

for i in range(N - 1, -1, -1):
    
    
    
    while robots[stack[-1]].l < robots[i].r:
        stack.pop()

    
    j = stack[-1]
    dp[i] = (dp[i + 1] + dp[j]) % MOD
    stack.append(i)

print(dp[0])

Solution (Python):
import bisect



def segfunc(x, y):
    return max(x, y)



ide_ele = -10000000000



class SegTree:
    """
    init(init_val, ide_ele): 配列init_valで初期化 O(N)
    update(k, x): k番目の値をxに更新 O(logN)
    query(l, r): 区間[l, r)をsegfuncしたものを返す O(logN)
    """
    def __init__(self, init_val, segfunc, ide_ele):
        """
        init_val: 配列の初期値
        segfunc: 区間にしたい操作
        ide_ele: 単位元
        n: 要素数
        num: n以上の最小の2のべき乗
        tree: セグメント木(1-index)
        """
        n = len(init_val)
        self.segfunc = segfunc
        self.ide_ele = ide_ele
        self.num = 1 << (n - 1).bit_length()
        self.tree = [ide_ele] * 2 * self.num
        
        for i in range(n):
            self.tree[self.num + i] = init_val[i]
        
        for i in range(self.num - 1, 0, -1):
            self.tree[i] = self.segfunc(self.tree[2 * i], self.tree[2 * i + 1])

    def update(self, k, x):
        """
        k番目の値をxに更新
        k: index(0-index)
        x: update value
        """
        k += self.num
        self.tree[k] = x
        while k > 1:
            self.tree[k >> 1] = self.segfunc(self.tree[k], self.tree[k ^ 1])
            k >>= 1

    def query(self, l, r):
        """
        [l, r)のsegfuncしたものを得る
        l: index(0-index)
        r: index(0-index)
        """
        res = self.ide_ele

        l += self.num
        r += self.num
        while l < r:
            if l & 1:
                res = self.segfunc(res, self.tree[l])
                l += 1
            if r & 1:
                res = self.segfunc(res, self.tree[r - 1])
            l >>= 1
            r >>= 1
        return res


mod = 998244353
n = int(input())
x = []
xd = []
for _ in range(n):
    _x, _d = map(int, input().split())
    x.append(_x)
    xd.append((_x, _d))
x.sort()
xd.sort()

init_val = [i for i in range(n + 1)]
seg = SegTree(init_val, segfunc, ide_ele)
dp = [1] * (n + 1)
for i in range(n - 1, -1, -1):
    j = bisect.bisect_left(x, xd[i][0] + xd[i][1])
    k = seg.query(i, j)
    seg.update(i, k)
    dp[i] = dp[i + 1] + dp[k + 1]
    dp[i] %= mod

print(dp[0])

Solution (Python):
from functools import reduce
import heapq, sys


input = sys.stdin.readline
N = int(input())
XD = sorted([tuple(map(int, input().split())) for _ in range(N)], key=lambda x: x[0], reverse=True)
P = 998244353


class Node:
    def __init__(self, ch):
        self.ch = ch
        if len(self.ch) == 0:
            self.score = 2
        else:
            self.score = reduce(lambda a, b: (a * b) % P, [ch.score for ch in self.ch]) + 1

hq = []  
heapq.heapify(hq)
for x, d in XD:
    ch = []
    while len(hq) != 0 and hq[0][0] < x+d:
        ch.append(heapq.heappop(hq)[1])
    heapq.heappush(hq, (x, Node(ch)))

ans = reduce(lambda a, b: (a * b) % P, [node.score for x, node in hq])
print(ans)

Solution (Python):
import sys
input = sys.stdin.readline
import bisect
MOD = 998244353
n = int(input())
XD = sorted([list(map(int, input().split())) for _ in range(n)])
X, D = zip(*XD)


C = list(range(n))

class RmaxQ:
    def __init__(self, original):
        self.n = len(original)
        self.INF = -float("inf")
        self.N0 = 1 << (self.n-1).bit_length()
        self.seg = [self.INF]*(self.N0 << 1)
        for i, j in enumerate(original, self.N0):
            self.seg[i] = j
        for i in range(self.N0-1, 0, -1):
            self.seg[i] = max(self.seg[2*i], self.seg[2*i+1])

    def get(self, i):
        return self.seg[i+self.N0]
        
    def update(self, i, x):
        i += self.N0
        self.seg[i] = x
        while i > 1:
            i >>= 1
            self.seg[i] = max(self.seg[2*i], self.seg[2*i+1])
                
    def query(self, l, r):
        res = self.INF
        l += self.N0
        r += self.N0
        while l < r:
            if r & 1:
                res = max(res, self.seg[r-1])
            if l & 1:
                res = max(res, self.seg[l])
                l += 1
            l >>= 1
            r >>= 1
     
        return res
    
seg = RmaxQ(C)
for i in range(n):
  x, d = XD[n-1-i]
  t = bisect.bisect_left(X, x+d)
  seg.update(n-1-i, max(t, seg.query(n-1-i, t)))

dp = [0]*(n+1)
l = [0]*n
l[-1] = n
dp[-1] = 1
for i in range(n):
  x, d = XD[n-1-i]
  m = bisect.bisect_left(X, x+d)
  t = seg.query(n-1-i, m)
  dp[n-1-i] = dp[n-i] + dp[t]
  dp[n-1-i] %= MOD
print(dp[0])