Buggy python submission (verdict: Time Limit Exceeded):
import sys
from bisect import bisect, bisect_left

class SquareDiv(): #区間の最大値を求める
    def __init__(self, N, V):
        k = 1
        while k ** 2 < N: k += 1
        self.array = [V] * k
        self.size = k
        self.indivisual = [V] * N

    def update(self, i, v): #i番目をvに更新する
        self.indivisual[i] = v
        self.array[i // self.size] = max(self.array[i // self.size], v)

    def search(self, left, right): #[left, right]の最大値を求める
        lk, rk = left // self.size, right // self.size
        if lk == rk:
            maxN = 0
            for i in range(left, right + 1): maxN = max(maxN, self.indivisual[i])
            return maxN
        else:
            maxN = self.search(left, (lk + 1) * self.size - 1)
            for k in range(lk + 1, rk): maxN = max(maxN, self.array[k])
            maxN = max(maxN, self.search(rk * self.size, right))
            return maxN

def solve():
    input = sys.stdin.readline
    N = int(input())
    R = [[int(i) for i in input().split()] for _ in range(N)]
    R.sort()
    mod = 998244353
    X = [R[i][0] for i in range(N)]
    Connect = SquareDiv(N, 0)
    DP = dict()
    DP[N] = 1
    for i in reversed(range(N)):
        right = max(i, Connect.search(i, bisect_left(X, sum(R[i])) - 1))
        Connect.update(i, right)
        DP[i] = (DP[right + 1] + DP[i + 1]) % mod
    print(DP[0])
    

    return 0

if __name__ == "__main__":
    solve()


Fixed submission:
import sys
from bisect import bisect, bisect_left

class SquareDiv(): #区間の最大値を求める
    def __init__(self, N, V):
        k = 1
        while k ** 2 < N: k += 1
        self.array = [V] * k
        self.size = k
        self.indivisual = [V] * N

    def update(self, i, v): #i番目をvに更新する
        self.indivisual[i] = v
        self.array[i // self.size] = max(self.array[i // self.size], v)

    def search(self, left, right): #[left, right]の最大値を求める
        lk, rk = left // self.size, right // self.size
        if lk == rk:
            maxN = 0
            for i in range(left, right + 1): maxN = max(maxN, self.indivisual[i])
            return maxN
        else:
            maxN = self.search(left, (lk + 1) * self.size - 1)
            for k in range(lk + 1, rk): maxN = max(maxN, self.array[k])
            maxN = max(maxN, self.search(rk * self.size, right))
            return maxN

def solve():
    input = sys.stdin.readline
    N = int(input())
    R = [[int(i) for i in input().split()] for _ in range(N)]
    R.sort()
    mod = 998244353
    X = [R[i][0] for i in range(N)]
    Connect = SquareDiv(N, 0)
    DP = dict()
    DP[N] = 1
    for i in reversed(range(N)):
        right = max(i, Connect.search(i, bisect_left(X, sum(R[i])) - 1))
        Connect.update(i, right)
        DP[i] = (DP[right + 1] + DP[i + 1]) % mod
    print(DP[0])
    

    return 0

if __name__ == "__main__":
    solve()

Buggy python submission (verdict: Time Limit Exceeded):
import sys
from bisect import bisect, bisect_left

class RMQ(): #range minimum query
    def __init__(self, N, V): #create segment tree with initial value V
        self.size = 1
        while self.size < N:
            self.size <<= 1
        self.tree = [V] * (2 * self.size - 1)
    
    def update(self, i, a): #update cell i by value a
        now = self.size - 1 + i 
        self.tree[now] = a
        while now > 0:
            now = (now - 1) // 2
            self.tree[now] = max(self.tree[2 * now + 1], self.tree[2 * now + 2])

    def search(self, lower, higher, lbound, hbound, pos): #search minimum value of [lower, higher) init: lbound = 0, hbound = self.size, pos = 0
        if higher <= lbound or hbound <= lower: return 0
        if lower <= lbound and hbound <= higher: return self.tree[pos]
        else:
            left = self.search(lower, higher, lbound, (lbound + hbound) // 2, 2 * pos + 1)
            right = self.search(lower, higher, (lbound + hbound) // 2, hbound, 2 * pos + 2)
            return max(left, right)

def solve():
    input = sys.stdin.readline
    N = int(input())
    R = [[int(i) for i in input().split()] for _ in range(N)]
    R.sort()
    mod = 998244353
    X = [R[i][0] for i in range(N)]
    Connect = RMQ(N, 0)
    DP = [1] * (N + 1)
    for i in reversed(range(N)):
        right = max(i, Connect.search(i, bisect_left(X, sum(R[i])), 0, Connect.size, 0))
        Connect.update(i, right)
        DP[i] = (DP[right + 1] + DP[i + 1]) % mod
    print(DP[0])
    

    return 0

if __name__ == "__main__":
    solve()

Fixed submission:
import sys
from bisect import bisect, bisect_left

class SquareDiv(): #区間の最大値を求める
    def __init__(self, N, V):
        k = 1
        while k ** 2 < N: k += 1
        self.array = [V] * k
        self.size = k
        self.indivisual = [V] * N

    def update(self, i, v): #i番目をvに更新する
        self.indivisual[i] = v
        self.array[i // self.size] = max(self.array[i // self.size], v)

    def search(self, left, right): #[left, right]の最大値を求める
        lk, rk = left // self.size, right // self.size
        if lk == rk:
            maxN = 0
            for i in range(left, right + 1): maxN = max(maxN, self.indivisual[i])
            return maxN
        else:
            maxN = self.search(left, (lk + 1) * self.size - 1)
            for k in range(lk + 1, rk): maxN = max(maxN, self.array[k])
            maxN = max(maxN, self.search(rk * self.size, right))
            return maxN

def solve():
    input = sys.stdin.readline
    N = int(input())
    R = [[int(i) for i in input().split()] for _ in range(N)]
    R.sort()
    mod = 998244353
    X = [R[i][0] for i in range(N)]
    Connect = SquareDiv(N, 0)
    DP = dict()
    DP[N] = 1
    for i in reversed(range(N)):
        right = max(i, Connect.search(i, bisect_left(X, sum(R[i])) - 1))
        Connect.update(i, right)
        DP[i] = (DP[right + 1] + DP[i + 1]) % mod
    print(DP[0])
    

    return 0

if __name__ == "__main__":
    solve()

Buggy python submission (verdict: Time Limit Exceeded):
import sys
from bisect import bisect, bisect_left

class LST(): #遅延セグ木
    def __init__(self, N, V): #create segment tree with initial value V
        self.size = 1
        while self.size < N: self.size <<= 1
        self.tree = [V] * (2 * self.size - 1)
        self.changed = [0] * (2 * self.size - 1) 

    def eval(self, i, left, right): #遅延評価, [left, right)
        t = self.changed[i]
        if t > 0:
            self.tree[i] = t
            if right - left > 1:
                self.changed[2 * i + 1] = t 
                self.changed[2 * i + 2] = t
            self.changed[i] = -1
    
    def update(self, v, lower, higher, lbound, hbound, pos): #update cell i by value a, pos = 0  
        self.eval(pos, lbound, hbound)    
        if higher <= lbound or hbound <= lower: return
        if lower <= lbound and hbound <= higher: 
            self.tree[pos] = v
            if hbound - lbound > 1: self.changed[2 * pos + 1] = self.changed[2 * pos + 2] = v
        else:
            self.update(v, lower, higher, lbound, (lbound + hbound) // 2, 2 * pos + 1)
            self.update(v, lower, higher, (lbound + hbound) // 2, hbound, 2 * pos + 2)
            self.tree[pos] = max(self.tree[2 * pos + 1], self.tree[2 * pos + 2])

    def search(self, lower, higher, lbound, hbound, pos): #search minimum value of [lower, higher) init: lbound = 0, hbound = self.size, pos = 0
        if higher <= lbound or hbound <= lower: return 0

        self.eval(pos, lbound, hbound)
        if lower <= lbound and hbound <= higher: return self.tree[pos]
        else:
            left = self.search(lower, higher, lbound, (lbound + hbound) // 2, 2 * pos + 1)
            right = self.search(lower, higher, (lbound + hbound) // 2, hbound, 2 * pos + 2)
            return max(left, right)

def solve():
    input = sys.stdin.readline
    N = int(input())
    R = [[int(i) for i in input().split()] for _ in range(N)]
    R.sort()
    mod = 998244353
    X = [R[i][0] for i in range(N)]
    D = [R[i][1] for i in range(N)]
    Connect = LST(N, 0)
    DP = [1] * (N + 1)
    for i in reversed(range(N)):
        right = max(i, Connect.search(i, bisect_left(X, X[i] + D[i]), 0, Connect.size, 0))
        Connect.update(right, i, i+1, 0, Connect.size, 0)
        DP[i] = (DP[right + 1] + DP[i + 1]) % mod
    print(DP[0])

    return 0

if __name__ == "__main__":
    solve()

Fixed submission:
import sys
from bisect import bisect, bisect_left

class SquareDiv(): #区間の最大値を求める
    def __init__(self, N, V):
        k = 1
        while k ** 2 < N: k += 1
        self.array = [V] * k
        self.size = k
        self.indivisual = [V] * N

    def update(self, i, v): #i番目をvに更新する
        self.indivisual[i] = v
        self.array[i // self.size] = max(self.array[i // self.size], v)

    def search(self, left, right): #[left, right]の最大値を求める
        lk, rk = left // self.size, right // self.size
        if lk == rk:
            maxN = 0
            for i in range(left, right + 1): maxN = max(maxN, self.indivisual[i])
            return maxN
        else:
            maxN = self.search(left, (lk + 1) * self.size - 1)
            for k in range(lk + 1, rk): maxN = max(maxN, self.array[k])
            maxN = max(maxN, self.search(rk * self.size, right))
            return maxN

def solve():
    input = sys.stdin.readline
    N = int(input())
    R = [[int(i) for i in input().split()] for _ in range(N)]
    R.sort()
    mod = 998244353
    X = [R[i][0] for i in range(N)]
    Connect = SquareDiv(N, 0)
    DP = dict()
    DP[N] = 1
    for i in reversed(range(N)):
        right = max(i, Connect.search(i, bisect_left(X, sum(R[i])) - 1))
        Connect.update(i, right)
        DP[i] = (DP[right + 1] + DP[i + 1]) % mod
    print(DP[0])
    

    return 0

if __name__ == "__main__":
    solve()

Buggy python submission (verdict: Time Limit Exceeded):
import sys
from bisect import bisect, bisect_left

class LST(): #遅延セグ木
    def __init__(self, N, V): #create segment tree with initial value V
        self.size = 1
        while self.size < N: self.size <<= 1
        self.tree = [V] * (2 * self.size - 1)
        self.changed = [0] * (2 * self.size - 1) 

    def eval(self, i, left, right): #遅延評価, [left, right)
        t = self.changed[i]
        if t > 0:
            self.tree[i] = t
            if right - left > 1:
                self.changed[2 * i + 1] = t 
                self.changed[2 * i + 2] = t
            self.changed[i] = -1
    
    def update(self, v, lower, higher, lbound, hbound, pos): #update cell i by value a, pos = 0  
        self.eval(pos, lbound, hbound)    
        if higher <= lbound or hbound <= lower: return
        if lower <= lbound and hbound <= higher: 
            self.tree[pos] = v
            if hbound - lbound > 1: self.changed[2 * pos + 1] = self.changed[2 * pos + 2] = v
        else:
            self.update(v, lower, higher, lbound, (lbound + hbound) // 2, 2 * pos + 1)
            self.update(v, lower, higher, (lbound + hbound) // 2, hbound, 2 * pos + 2)
            self.tree[pos] = max(self.tree[2 * pos + 1], self.tree[2 * pos + 2])

    def search(self, lower, higher, lbound, hbound, pos): #search minimum value of [lower, higher) init: lbound = 0, hbound = self.size, pos = 0
        if higher <= lbound or hbound <= lower: return 0

        self.eval(pos, lbound, hbound)
        if lower <= lbound and hbound <= higher: return self.tree[pos]
        else:
            left = self.search(lower, higher, lbound, (lbound + hbound) // 2, 2 * pos + 1)
            right = self.search(lower, higher, (lbound + hbound) // 2, hbound, 2 * pos + 2)
            return max(left, right)

def solve():
    input = sys.stdin.readline
    N = int(input())
    R = [[int(i) for i in input().split()] for _ in range(N)]
    R.sort()
    mod = 998244353
    X = [R[i][0] for i in range(N)]
    D = [R[i][1] for i in range(N)]
    Connect = LST(N, 0)
    DP = [1] * (N + 1)
    for i in reversed(range(N)):
        right = max(i, Connect.search(i, bisect_left(X, X[i] + D[i]), 0, Connect.size, 0))
        Connect.update(right, i, i+1, 0, Connect.size, 0)
        DP[i] = (DP[right + 1] + DP[i + 1]) % mod
    print(DP[0])

    return 0

if __name__ == "__main__":
    solve()

Fixed submission:
import sys
from bisect import bisect, bisect_left

class SquareDiv(): #区間の最大値を求める
    def __init__(self, N, V):
        k = 1
        while k ** 2 < N: k += 1
        self.array = [V] * k
        self.size = k
        self.indivisual = [V] * N

    def update(self, i, v): #i番目をvに更新する
        self.indivisual[i] = v
        self.array[i // self.size] = max(self.array[i // self.size], v)

    def search(self, left, right): #[left, right]の最大値を求める
        lk, rk = left // self.size, right // self.size
        if lk == rk:
            maxN = 0
            for i in range(left, right + 1): maxN = max(maxN, self.indivisual[i])
            return maxN
        else:
            maxN = self.search(left, (lk + 1) * self.size - 1)
            for k in range(lk + 1, rk): maxN = max(maxN, self.array[k])
            maxN = max(maxN, self.search(rk * self.size, right))
            return maxN

def solve():
    input = sys.stdin.readline
    N = int(input())
    R = [[int(i) for i in input().split()] for _ in range(N)]
    R.sort()
    mod = 998244353
    X = [R[i][0] for i in range(N)]
    Connect = SquareDiv(N, 0)
    DP = dict()
    DP[N] = 1
    for i in reversed(range(N)):
        right = max(i, Connect.search(i, bisect_left(X, sum(R[i])) - 1))
        Connect.update(i, right)
        DP[i] = (DP[right + 1] + DP[i + 1]) % mod
    print(DP[0])
    

    return 0

if __name__ == "__main__":
    solve()

Buggy python submission (verdict: Time Limit Exceeded):
import sys
from bisect import bisect, bisect_left

class RMQ(): #range minimum query
    def __init__(self, N, V): #create segment tree with initial value V
        d, k = 1, 0
        while d < N:
            d <<= 1
            k += 1
        self.tree = [V] * (2 * d - 1)
        self.size = d
    
    def update(self, i, a): #update cell i by value a
        now = self.size - 1 + i 
        self.tree[now] = a
        while now > 0:
            now = (now - 1) // 2
            self.tree[now] = max(self.tree[2 * now + 1], self.tree[2 * now + 2])

    def search(self, lower, higher, lbound, hbound, pos): #search minimum value of [lower, higher) init: lbound = 0, hbound = self.size, pos = 0
        if higher <= lbound or hbound <= lower: return 0
        if lower <= lbound and hbound <= higher: return self.tree[pos]
        else:
            left = self.search(lower, higher, lbound, (lbound + hbound) // 2, 2 * pos + 1)
            right = self.search(lower, higher, (lbound + hbound) // 2, hbound, 2 * pos + 2)
            return max(left, right)

def solve():
    input = sys.stdin.readline
    N = int(input())
    R = [[int(i) for i in input().split()] for _ in range(N)]
    R.sort()
    mod = 998244353
    X = [R[i][0] for i in range(N)]
    D = [R[i][1] for i in range(N)]
    Connect = RMQ(N, 0)
    DP = [1] * (N + 1)
    for i in reversed(range(N)):
        right = max(i, Connect.search(i, bisect_left(X, X[i] + D[i]), 0, Connect.size, 0))
        Connect.update(i, right)
        DP[i] = (DP[right + 1] + DP[i + 1]) % mod
    print(DP[0])
    

    return 0

if __name__ == "__main__":
    solve()

Fixed submission:
import sys
from bisect import bisect, bisect_left

class SquareDiv(): #区間の最大値を求める
    def __init__(self, N, V):
        k = 1
        while k ** 2 < N: k += 1
        self.array = [V] * k
        self.size = k
        self.indivisual = [V] * N

    def update(self, i, v): #i番目をvに更新する
        self.indivisual[i] = v
        self.array[i // self.size] = max(self.array[i // self.size], v)

    def search(self, left, right): #[left, right]の最大値を求める
        lk, rk = left // self.size, right // self.size
        if lk == rk:
            maxN = 0
            for i in range(left, right + 1): maxN = max(maxN, self.indivisual[i])
            return maxN
        else:
            maxN = self.search(left, (lk + 1) * self.size - 1)
            for k in range(lk + 1, rk): maxN = max(maxN, self.array[k])
            maxN = max(maxN, self.search(rk * self.size, right))
            return maxN

def solve():
    input = sys.stdin.readline
    N = int(input())
    R = [[int(i) for i in input().split()] for _ in range(N)]
    R.sort()
    mod = 998244353
    X = [R[i][0] for i in range(N)]
    Connect = SquareDiv(N, 0)
    DP = dict()
    DP[N] = 1
    for i in reversed(range(N)):
        right = max(i, Connect.search(i, bisect_left(X, sum(R[i])) - 1))
        Connect.update(i, right)
        DP[i] = (DP[right + 1] + DP[i + 1]) % mod
    print(DP[0])
    

    return 0

if __name__ == "__main__":
    solve()

Buggy python submission (verdict: Time Limit Exceeded):
import sys
from bisect import bisect, bisect_left

class RMQ(): #range minimum query
    def __init__(self, N, V): #create segment tree with initial value V
        d, k = 1, 0
        while d < N:
            d <<= 1
            k += 1
        self.tree = [V for _ in range(2 * d - 1)]
        self.size = d
    
    def update(self, i, a): #update cell i by value a
        now = self.size - 1 + i 
        self.tree[now] = a
        while now > 0:
            now = (now - 1) // 2
            self.tree[now] = max(self.tree[2 * now + 1], self.tree[2 * now + 2])
        #print(self.tree)

    def search(self, lower, higher, lbound, hbound, pos): #search minimum value of [lower, higher) init: lbound = 0, hbound = self.size, pos = 0
        if higher <= lbound or hbound <= lower: return 0
        if lower <= lbound and hbound <= higher: return self.tree[pos]
        else:
            left = self.search(lower, higher, lbound, (lbound + hbound) // 2, 2 * pos + 1)
            right = self.search(lower, higher, (lbound + hbound) // 2, hbound, 2 * pos + 2)
            return max(left, right)

def solve():
    input = sys.stdin.readline
    N = int(input())
    R = [[int(i) for i in input().split()] for _ in range(N)]
    R.sort()
    mod = 998244353
    X = [R[i][0] for i in range(N)]
    D = [R[i][1] for i in range(N)]
    Connect = RMQ(N, 0)
    DP = [1] * (N + 1)
    for i in reversed(range(N)):
        right = max(i, Connect.search(i, bisect_left(X, X[i] + D[i]), 0, Connect.size, 0))
        Connect.update(i, right)
        DP[i] = (DP[right + 1] + DP[i + 1]) % mod
    print(DP[0])
    

    return 0

if __name__ == "__main__":
    solve()

Fixed submission:
import sys
from bisect import bisect, bisect_left

class SquareDiv(): #区間の最大値を求める
    def __init__(self, N, V):
        k = 1
        while k ** 2 < N: k += 1
        self.array = [V] * k
        self.size = k
        self.indivisual = [V] * N

    def update(self, i, v): #i番目をvに更新する
        self.indivisual[i] = v
        self.array[i // self.size] = max(self.array[i // self.size], v)

    def search(self, left, right): #[left, right]の最大値を求める
        lk, rk = left // self.size, right // self.size
        if lk == rk:
            maxN = 0
            for i in range(left, right + 1): maxN = max(maxN, self.indivisual[i])
            return maxN
        else:
            maxN = self.search(left, (lk + 1) * self.size - 1)
            for k in range(lk + 1, rk): maxN = max(maxN, self.array[k])
            maxN = max(maxN, self.search(rk * self.size, right))
            return maxN

def solve():
    input = sys.stdin.readline
    N = int(input())
    R = [[int(i) for i in input().split()] for _ in range(N)]
    R.sort()
    mod = 998244353
    X = [R[i][0] for i in range(N)]
    Connect = SquareDiv(N, 0)
    DP = dict()
    DP[N] = 1
    for i in reversed(range(N)):
        right = max(i, Connect.search(i, bisect_left(X, sum(R[i])) - 1))
        Connect.update(i, right)
        DP[i] = (DP[right + 1] + DP[i + 1]) % mod
    print(DP[0])
    

    return 0

if __name__ == "__main__":
    solve()

Buggy python submission (verdict: Time Limit Exceeded):
import sys
from bisect import bisect, bisect_left

class RMQ(): #range minimum query
    def __init__(self, N, V): #create segment tree with initial value V
        d, k = 1, 0
        while d < N:
            d <<= 1
            k += 1
        self.tree = [V for _ in range(2 * d - 1)]
        self.size = d
    
    def update(self, i, a): #update cell i by value a
        now = self.size - 1 + i 
        self.tree[now] = a
        while now > 0:
            now = (now - 1) // 2
            self.tree[now] = max(self.tree[2 * now + 1], self.tree[2 * now + 2])
        #print(self.tree)

    def search(self, lower, higher, lbound, hbound, pos): #search minimum value of [lower, higher) init: lbound = 0, hbound = self.size, pos = 0
        if higher <= lbound or hbound <= lower: return 0
        if lower <= lbound and hbound <= higher: return self.tree[pos]
        else:
            left = self.search(lower, higher, lbound, (lbound + hbound) // 2, 2 * pos + 1)
            right = self.search(lower, higher, (lbound + hbound) // 2, hbound, 2 * pos + 2)
            return max(left, right)

def solve():
    input = sys.stdin.readline
    N = int(input())
    R = [[int(i) for i in input().split()] for _ in range(N)]
    R.sort()
    mod = 998244353
    X = [R[i][0] for i in range(N)]
    D = [R[i][1] for i in range(N)]
    Edge = [i for i in range(N)]
    Connect = RMQ(N, 0)
    for i in range(N):
        Connect.update(i, i)
        k = bisect_left(X, X[i] + D[i])
        Edge[i] = k - 1

    for i in reversed(range(N)):
        Connect.update(i, Connect.search(i, Edge[i] + 1, 0, Connect.size, 0))

    DP = [0] * N
    DP.append(1)
    for i in reversed(range(N)):
        right =  Connect.tree[Connect.size - 1 + i]
        DP[i] = (DP[right+1] + DP[i+1]) % mod
        
    print(DP[0])
    

    return 0

if __name__ == "__main__":
    solve()

Fixed submission:
import sys
from bisect import bisect, bisect_left

class SquareDiv(): #区間の最大値を求める
    def __init__(self, N, V):
        k = 1
        while k ** 2 < N: k += 1
        self.array = [V] * k
        self.size = k
        self.indivisual = [V] * N

    def update(self, i, v): #i番目をvに更新する
        self.indivisual[i] = v
        self.array[i // self.size] = max(self.array[i // self.size], v)

    def search(self, left, right): #[left, right]の最大値を求める
        lk, rk = left // self.size, right // self.size
        if lk == rk:
            maxN = 0
            for i in range(left, right + 1): maxN = max(maxN, self.indivisual[i])
            return maxN
        else:
            maxN = self.search(left, (lk + 1) * self.size - 1)
            for k in range(lk + 1, rk): maxN = max(maxN, self.array[k])
            maxN = max(maxN, self.search(rk * self.size, right))
            return maxN

def solve():
    input = sys.stdin.readline
    N = int(input())
    R = [[int(i) for i in input().split()] for _ in range(N)]
    R.sort()
    mod = 998244353
    X = [R[i][0] for i in range(N)]
    Connect = SquareDiv(N, 0)
    DP = dict()
    DP[N] = 1
    for i in reversed(range(N)):
        right = max(i, Connect.search(i, bisect_left(X, sum(R[i])) - 1))
        Connect.update(i, right)
        DP[i] = (DP[right + 1] + DP[i + 1]) % mod
    print(DP[0])
    

    return 0

if __name__ == "__main__":
    solve()

Buggy python submission (verdict: Time Limit Exceeded):
import sys
from bisect import bisect, bisect_left
sys.setrecursionlimit(1000000)

def count(i, Edge, Connect):
    if Edge[i] == i: 
        Connect[i] = 0
        return 0
    if Connect[i] > -1: return Connect[i]   
    far = 0
    for k in range(i + 1, Edge[i] + 1): far = max(far, k - i + count(k, Edge, Connect))
    Connect[i] = far
    return far

def solve():
    input = sys.stdin.readline
    N = int(input())
    R = [[int(i) for i in input().split()] for _ in range(N)]
    R.sort()
    mod = 998244353
    X = [R[i][0] for i in range(N)]
    D = [R[i][1] for i in range(N)]
    Edge = [i for i in range(N)]
    Connect = [-1] * N
    for i in range(N):
        k = bisect_left(X, X[i] + D[i])
        Edge[i] = k - 1

    #print(Edge)
    for i in range(N):
        if Connect[i] == -1: count(i, Edge, Connect)
    #print(Connect)
    DP = [0] * N
    DP.append(1)
    for i in reversed(range(N)):
        right = i + Connect[i]
        DP[i] = (DP[right + 1] + DP[i+1]) % mod
        
    print(DP[0])
    

    return 0

if __name__ == "__main__":
    solve()

Fixed submission:
import sys
from bisect import bisect, bisect_left

class SquareDiv(): #区間の最大値を求める
    def __init__(self, N, V):
        k = 1
        while k ** 2 < N: k += 1
        self.array = [V] * k
        self.size = k
        self.indivisual = [V] * N

    def update(self, i, v): #i番目をvに更新する
        self.indivisual[i] = v
        self.array[i // self.size] = max(self.array[i // self.size], v)

    def search(self, left, right): #[left, right]の最大値を求める
        lk, rk = left // self.size, right // self.size
        if lk == rk:
            maxN = 0
            for i in range(left, right + 1): maxN = max(maxN, self.indivisual[i])
            return maxN
        else:
            maxN = self.search(left, (lk + 1) * self.size - 1)
            for k in range(lk + 1, rk): maxN = max(maxN, self.array[k])
            maxN = max(maxN, self.search(rk * self.size, right))
            return maxN

def solve():
    input = sys.stdin.readline
    N = int(input())
    R = [[int(i) for i in input().split()] for _ in range(N)]
    R.sort()
    mod = 998244353
    X = [R[i][0] for i in range(N)]
    Connect = SquareDiv(N, 0)
    DP = dict()
    DP[N] = 1
    for i in reversed(range(N)):
        right = max(i, Connect.search(i, bisect_left(X, sum(R[i])) - 1))
        Connect.update(i, right)
        DP[i] = (DP[right + 1] + DP[i + 1]) % mod
    print(DP[0])
    

    return 0

if __name__ == "__main__":
    solve()

Buggy python submission (verdict: Time Limit Exceeded):
import sys
from bisect import bisect, bisect_left
sys.setrecursionlimit(1000000)

def count(i, Edge, Connect):
    if Edge[i] == i: 
        Connect[i] = 0
        return 0
    if Connect[i] > -1: return Connect[i]   
    far = 0
    for k in range(i + 1, Edge[i] + 1): far = max(far, k - i + count(k, Edge, Connect))
    Connect[i] = far
    return far

def solve():
    input = sys.stdin.readline
    N = int(input())
    R = [[int(i) for i in input().split()] for _ in range(N)]
    R.sort()
    mod = 998244353
    X = [R[i][0] for i in range(N)]
    D = [R[i][1] for i in range(N)]
    Edge = [i for i in range(N)]
    Connect = [-1] * N
    for i in range(N):
        k = bisect_left(X, X[i] + D[i])
        Edge[i] = k - 1

    #print(Edge)
    for i in range(N):
        if Connect[i] == -1: count(i, Edge, Connect)
    #print(Connect)
    DP = [0] * N
    DP.append(1)
    for i in reversed(range(N)):
        right = i + Connect[i]
        DP[i] = (DP[right + 1] + DP[i+1]) % mod
        
    print(DP[0])
    

    return 0

if __name__ == "__main__":
    solve()

Fixed submission:
import sys
from bisect import bisect, bisect_left

class SquareDiv(): #区間の最大値を求める
    def __init__(self, N, V):
        k = 1
        while k ** 2 < N: k += 1
        self.array = [V] * k
        self.size = k
        self.indivisual = [V] * N

    def update(self, i, v): #i番目をvに更新する
        self.indivisual[i] = v
        self.array[i // self.size] = max(self.array[i // self.size], v)

    def search(self, left, right): #[left, right]の最大値を求める
        lk, rk = left // self.size, right // self.size
        if lk == rk:
            maxN = 0
            for i in range(left, right + 1): maxN = max(maxN, self.indivisual[i])
            return maxN
        else:
            maxN = self.search(left, (lk + 1) * self.size - 1)
            for k in range(lk + 1, rk): maxN = max(maxN, self.array[k])
            maxN = max(maxN, self.search(rk * self.size, right))
            return maxN

def solve():
    input = sys.stdin.readline
    N = int(input())
    R = [[int(i) for i in input().split()] for _ in range(N)]
    R.sort()
    mod = 998244353
    X = [R[i][0] for i in range(N)]
    Connect = SquareDiv(N, 0)
    DP = dict()
    DP[N] = 1
    for i in reversed(range(N)):
        right = max(i, Connect.search(i, bisect_left(X, sum(R[i])) - 1))
        Connect.update(i, right)
        DP[i] = (DP[right + 1] + DP[i + 1]) % mod
    print(DP[0])
    

    return 0

if __name__ == "__main__":
    solve()