Buggy python submission (verdict: Time Limit Exceeded):
def main():
    from bisect import bisect_left

    import sys
    input = sys.stdin.readline
    N = int(input())

    MOD = 998244353

    X = []
    X_append = X.append
    dic = dict() #Xから動ける先の場所

    for _ in range(N):
        x, d = map(int, input().split())
        X_append(x)
        dic[x] = x + d

    X.sort()
    lst = []
    lst_append = lst.append
    for x in X:
        tmp = bisect_left(X, dic[x])
        lst_append(tmp)

    #ここまででどれを動かしたら何番まで消えるかがわかった
    dp = [[-1] * (2) for _ in range(N + 1)]

    dp[N][0] = 1
    dp[N][1] = 0

    class SegmentTree:
        __slots__ = ["_default_value", "_seg_func", "_modifying_func", "_size", "_tree"]

        def __init__(self, initial_values: "Sequence", default_value: "Union[int, str]", seg_func: "Callable",
                    modifying_func: "Optional[Callable]" = None) -> None:
            self._default_value = default_value
            self._seg_func = seg_func
            self._modifying_func = modifying_func
            self._size = 1 << (len(initial_values) - 1).bit_length()
            self._tree = self._build(initial_values)

        def _build(self, initial_values: "Sequence") -> "List":
            """Build a segment tree with initial values."""
            tree = [self._default_value] * (2 * self._size)

            if self._modifying_func:
                initial_values = map(self._modifying_func, initial_values)

            for idx, val in enumerate(initial_values):  # set a tree
                tree[idx + self._size - 1] = val

            for idx in range(self._size - 2, -1, -1):  # build
                tree[idx] = self._seg_func(tree[2 * idx + 1], tree[2 * idx + 2])

            return tree

        def update(self, index: int, value: int) -> None:
            """Update index to value."""
            index += self._size - 1
            if self._modifying_func:
                value = self._modifying_func(value)
            self._tree[index] = value
            while index:
                index = (index - 1) // 2
                self._tree[index] = self._seg_func(self._tree[2 * index + 1], self._tree[2 * index + 2])

        def query(self, left: int, right: int) -> "Union[int, str]":
            """Respond to query in [left, right]."""
            left += self._size
            right += self._size
            result = self._default_value
            while left < right:
                if left & 1:
                    result = self._seg_func(result, self._tree[left - 1])
                    left += 1
                if right & 1:
                    right -= 1
                    result = self._seg_func(result, self._tree[right - 1])
                left >>= 1
                right >>= 1
            return result

    tree = SegmentTree(lst, 0, max, None)

    for i in range(N - 1, -1, -1):
        tmp = max(i + 1, tree.query(i, lst[i])) #動くべき場所
        # print (tmp)
        dp[i][0] = (dp[i + 1][0] + dp[i + 1][1]) % MOD
        dp[i][1] = (dp[tmp][0] + dp[tmp][1]) % MOD
        tree.update(i, tmp)

    print (dp[0][0] + dp[0][1])

    # for i in range(N - 1, -1, -1):
    #     dp[i][0] = dp[i + 1][0] + dp[i + 1][1]
    #     dp[i][1] = dp[move[i]][0] + dp[move[i]][1]



if __name__ == '__main__':
    main()

Fixed submission:
def main():
    from bisect import bisect_left

    import sys
    input = sys.stdin.readline
    N = int(input())

    MOD = 998244353

    X = []
    X_append = X.append
    dic = dict() #Xから動ける先の場所

    for _ in range(N):
        x, d = map(int, input().split())
        X_append(x)
        dic[x] = x + d

    X.sort()
    lst = []
    lst_append = lst.append
    for x in X:
        tmp = bisect_left(X, dic[x])
        lst_append(tmp)

    #ここまででどれを動かしたら何番まで消えるかがわかった
    dp = [[-1] * (2) for _ in range(N + 1)]

    dp[N][0] = 1
    dp[N][1] = 0

    class SegmentTree:
        __slots__ = ["_default_value", "_seg_func", "_modifying_func", "_size", "_tree"]

        def __init__(self, initial_values: "Sequence", default_value: "Union[int, str]", seg_func: "Callable",
                    modifying_func: "Optional[Callable]" = None) -> None:
            self._default_value = default_value
            self._seg_func = seg_func
            self._modifying_func = modifying_func
            self._size = 1 << (len(initial_values) - 1).bit_length()
            self._tree = self._build(initial_values)

        def _build(self, initial_values: "Sequence") -> "List":
            """Build a segment tree with initial values."""
            tree = [self._default_value] * (2 * self._size)

            if self._modifying_func:
                initial_values = map(self._modifying_func, initial_values)

            for idx, val in enumerate(initial_values):  # set a tree
                tree[idx + self._size - 1] = val

            for idx in range(self._size - 2, -1, -1):  # build
                tree[idx] = self._seg_func(tree[2 * idx + 1], tree[2 * idx + 2])

            return tree

        def update(self, index: int, value: int) -> None:
            """Update index to value."""
            index += self._size - 1
            if self._modifying_func:
                value = self._modifying_func(value)
            self._tree[index] = value
            while index:
                index = (index - 1) // 2
                self._tree[index] = self._seg_func(self._tree[2 * index + 1], self._tree[2 * index + 2])

        def query(self, left: int, right: int) -> "Union[int, str]":
            """Respond to query in [left, right]."""
            left += self._size
            right += self._size
            result = self._default_value
            while left < right:
                if left & 1:
                    result = self._seg_func(result, self._tree[left - 1])
                    left += 1
                if right & 1:
                    right -= 1
                    result = self._seg_func(result, self._tree[right - 1])
                left >>= 1
                right >>= 1
            return result

    tree = SegmentTree(lst, 0, max, None)

    for i in range(N - 1, -1, -1):
        tmp = max(i + 1, tree.query(i, lst[i])) #動くべき場所
        # print (tmp)
        dp[i][0] = (dp[i + 1][0] + dp[i + 1][1]) % MOD
        dp[i][1] = (dp[tmp][0] + dp[tmp][1]) % MOD
        tree.update(i, tmp)

    print ((dp[0][0] + dp[0][1]) % MOD)

    # for i in range(N - 1, -1, -1):
    #     dp[i][0] = dp[i + 1][0] + dp[i + 1][1]
    #     dp[i][1] = dp[move[i]][0] + dp[move[i]][1]



if __name__ == '__main__':
    main()

Buggy python submission (verdict: Time Limit Exceeded):
def main():
    from bisect import bisect_left

    import sys
    input = sys.stdin.readline
    N = int(input())

    MOD = 998244353

    X = []
    X_append = X.append
    dic = dict() #Xから動ける先の場所

    for _ in range(N):
        x, d = map(int, input().split())
        X_append(x)
        dic[x] = x + d

    X.sort()
    lst = []
    lst_append = lst.append
    for x in X:
        tmp = bisect_left(X, dic[x])
        lst_append(tmp)

    move = [0] * N

    INT_MIN = -10 ** 18
    MAX_N = 10 ** 6

    data = [INT_MIN] * (2 * MAX_N - 1)

    def init(n_):
        #簡単にするために2のべき乗に揃える
        n = 1
        while n < n_:
            n *= 2
        return n

    n = init(N)

    def update(k, a):
        k += n - 1
        data[k] = a
        while k > 0:
            k = (k - 1) // 2
            data[k] = max(data[2 * k + 1], data[2 * k + 2])

    def query(a, b, k = 0, l = 0, r = n):
        if r <= a or b <= l:
            return INT_MIN
        if a <= l and r <= b:
            return data[k]
        else:
            v1 = query(a, b, 2 * k + 1, l, (l + r)//2)
            v2 = query(a, b, 2 * k + 2, (l + r)//2, r)
            return max(v1, v2)

    def initialize(A): #リストAを与えて初期化する
        for i, a in enumerate(A):
            data[i + n - 1] = a
        for i in range(N + n - 1, 0, -2):
            tmp = i
            tmp = (tmp - 1) //2
            data[tmp] = max(data[tmp * 2 + 1], data[tmp * 2 + 2])

    #初期化
    initialize(lst)

    #ここまででどれを動かしたら何番まで消えるかがわかった
    dp = [[-1] * (2) for _ in range(N + 1)]

    dp[N][0] = 1
    dp[N][1] = 0

    for i in range(N - 1, -1, -1):
        tmp = max(i + 1, query(i, lst[i])) #動くべき場所
        # print (tmp)
        dp[i][0] = (dp[i + 1][0] + dp[i + 1][1]) % MOD
        dp[i][1] = (dp[tmp][0] + dp[tmp][1]) % MOD
        update(i, tmp)

    print (dp[0][0] + dp[0][1])

    # for i in range(N - 1, -1, -1):
    #     dp[i][0] = dp[i + 1][0] + dp[i + 1][1]
    #     dp[i][1] = dp[move[i]][0] + dp[move[i]][1]

if __name__ == '__main__':
    main()

Fixed submission:
def main():
    from bisect import bisect_left

    import sys
    input = sys.stdin.readline
    N = int(input())

    MOD = 998244353

    X = []
    X_append = X.append
    dic = dict() #Xから動ける先の場所

    for _ in range(N):
        x, d = map(int, input().split())
        X_append(x)
        dic[x] = x + d

    X.sort()
    lst = []
    lst_append = lst.append
    for x in X:
        tmp = bisect_left(X, dic[x])
        lst_append(tmp)

    #ここまででどれを動かしたら何番まで消えるかがわかった
    dp = [[-1] * (2) for _ in range(N + 1)]

    dp[N][0] = 1
    dp[N][1] = 0

    class SegmentTree:
        __slots__ = ["_default_value", "_seg_func", "_modifying_func", "_size", "_tree"]

        def __init__(self, initial_values: "Sequence", default_value: "Union[int, str]", seg_func: "Callable",
                    modifying_func: "Optional[Callable]" = None) -> None:
            self._default_value = default_value
            self._seg_func = seg_func
            self._modifying_func = modifying_func
            self._size = 1 << (len(initial_values) - 1).bit_length()
            self._tree = self._build(initial_values)

        def _build(self, initial_values: "Sequence") -> "List":
            """Build a segment tree with initial values."""
            tree = [self._default_value] * (2 * self._size)

            if self._modifying_func:
                initial_values = map(self._modifying_func, initial_values)

            for idx, val in enumerate(initial_values):  # set a tree
                tree[idx + self._size - 1] = val

            for idx in range(self._size - 2, -1, -1):  # build
                tree[idx] = self._seg_func(tree[2 * idx + 1], tree[2 * idx + 2])

            return tree

        def update(self, index: int, value: int) -> None:
            """Update index to value."""
            index += self._size - 1
            if self._modifying_func:
                value = self._modifying_func(value)
            self._tree[index] = value
            while index:
                index = (index - 1) // 2
                self._tree[index] = self._seg_func(self._tree[2 * index + 1], self._tree[2 * index + 2])

        def query(self, left: int, right: int) -> "Union[int, str]":
            """Respond to query in [left, right]."""
            left += self._size
            right += self._size
            result = self._default_value
            while left < right:
                if left & 1:
                    result = self._seg_func(result, self._tree[left - 1])
                    left += 1
                if right & 1:
                    right -= 1
                    result = self._seg_func(result, self._tree[right - 1])
                left >>= 1
                right >>= 1
            return result

    tree = SegmentTree(lst, 0, max, None)

    for i in range(N - 1, -1, -1):
        tmp = max(i + 1, tree.query(i, lst[i])) #動くべき場所
        # print (tmp)
        dp[i][0] = (dp[i + 1][0] + dp[i + 1][1]) % MOD
        dp[i][1] = (dp[tmp][0] + dp[tmp][1]) % MOD
        tree.update(i, tmp)

    print ((dp[0][0] + dp[0][1]) % MOD)

    # for i in range(N - 1, -1, -1):
    #     dp[i][0] = dp[i + 1][0] + dp[i + 1][1]
    #     dp[i][1] = dp[move[i]][0] + dp[move[i]][1]



if __name__ == '__main__':
    main()