CodeEff/ECCO huggingface dataset:
# Original solution
from bisect import bisect
from itertools import accumulate
from functools import reduce
from sys import setrecursionlimit

setrecursionlimit(10000000)

MOD = 998244353

def solve(robots):
    N = len(robots)
    robots.sort()

    parent = [None]*(N+1)

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

    adj = [list() for _ in range(N+1)]
    for i,p in enumerate(parent[1:],start=1):
        adj[p].append(i)

    rec = lambda i: reduce(lambda a,b:a*b%MOD, (rec(j)+1 for j in adj[i]), 1)

    return rec(0)

if __name__ == '__main__':
    N = int(eval(input()))
    robots = [tuple(map(int,input().split())) for _ in range(N)]
    print((solve(robots)))

# Optimized solution
from bisect import bisect
from itertools import accumulate
from functools import reduce
from sys import setrecursionlimit

setrecursionlimit(10000000)

MOD = 998244353

def solve(robots):
    N = len(robots)
    robots.sort()

    parent = [None]*(N+1)

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

    dp = [1]*(N+1)
    for i in reversed(list(range(1,N+1))):
        p = parent[i]
        dp[p] *= dp[i]+1
        dp[p] %= MOD
    return dp[0]

if __name__ == '__main__':
    N = int(eval(input()))
    robots = [tuple(map(int,input().split())) for _ in range(N)]
    print((solve(robots)))
# Original solution
import sys
from bisect import bisect_left
from operator import itemgetter


class SegTreeMax:
    """
    以下のクエリを処理する
    1.update:  i番目の値をxに更新する
    2.get_min: 区間[l, r)の最小値を得る
    """

    def __init__(self, n, INF):
        """
        :param n: 要素数
        :param INF: 初期値（入りうる要素より十分に大きな数）
        """
        n2 = 1 << (n - 1).bit_length()
        self.offset = n2
        self.tree = [INF] * (n2 << 1)
        self.INF = INF

    def initialize(self, arr):
        for i, v in enumerate(arr, start=self.offset):
            self.tree[i] = v
        for i in range(self.offset - 1, 0, -1):
            j = i << 1
            self.tree[i] = max(self.tree[j], self.tree[j + 1])

    def update(self, i, x):
        """
        i番目の値をxに更新
        :param i: index(0-indexed)
        :param x: update value
        """
        i += self.offset
        self.tree[i] = x
        while i > 1:
            y = self.tree[i ^ 1]
            if y >= x:
                break
            i >>= 1
            self.tree[i] = x

    def get_max(self, a, b):
        """
        [a, b)の最大値を得る
        :param a: index(0-indexed)
        :param b: index(0-indexed)
        """
        result = self.INF

        l = a + self.offset
        r = b + self.offset
        while l < r:
            if r & 1:
                result = max(result, self.tree[r - 1])
            if l & 1:
                result = max(result, self.tree[l])
                l += 1
            l >>= 1
            r >>= 1

        return result


n, *xd = list(map(int, sys.stdin.buffer.read().split()))
MOD = 998244353
xd = sorted(zip(xd[0::2], xd[1::2]))
xxx = list(map(itemgetter(0), xd))
ans = [0] * (n + 1)
skip = list(range(1, n + 1))
ans[n] = 1
sgt = SegTreeMax(n + 1, 0)
sgt.initialize(list(range(1, n + 2)))
for i in range(n - 1, -1, -1):
    x, d = xd[i]
    r = x + d
    j = bisect_left(xxx, r)
    k = sgt.get_max(i, j)
    ans[i] = (ans[i + 1] + ans[k]) % MOD
    sgt.update(i, k)
print((ans[0]))


# Optimized solution
import sys
from operator import itemgetter

n, *xd = list(map(int, sys.stdin.buffer.read().split()))
MOD = 998244353
xd = sorted(zip(xd[0::2], xd[1::2]))
xxx = list(map(itemgetter(0), xd)) + [10 ** 10]
ans = [0] * n + [1]
stack = [n]

for i in range(n - 1, -1, -1):
    x, d = xd[i]
    r = x + d
    while r > xxx[stack[-1]]:
        stack.pop()
    ans[i] = (ans[i + 1] + ans[stack[-1]]) % MOD
    stack.append(i)
print((ans[0]))
# Original solution
from heapq import *
import sys

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

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

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

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

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

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

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

    __radd__ = __add__
    __rmul__ = __mul__

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

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

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

md = 998244353

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

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

main()


# Optimized solution
from heapq import *
import sys

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

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

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

main()
# Original solution
from bisect import bisect_left
from heapq import heappush, heappop

N = int(eval(input()))
XD = [[int(i) for i in input().split()] for _ in range(N)]

mod = 998244353

XD.sort()

class SegTree:
  def __init__(self, n, v, f) :
    i = 1
    while i < n : 
      i <<= 1
    self.n = i
    self.v = v
    self.f = f
    self.tree = [v] * (i << 1)

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

  # [l, r)
  def query(self, l, r) :
    l = l + self.n
    r = r + self.n
    s = self.v
    while l < r :
      if r & 1 :
        r -= 1
        s = self.f(s, self.tree[r - 1])
      if l & 1 :
        s = self.f(s, self.tree[l - 1])
        l += 1
      l >>= 1
      r >>= 1
    return s

INF = 1 << 60
ST = SegTree(N, -INF, max)

xs = [x for x, _ in XD]
dest = [0] * N
for i in range(N - 1, -1, -1) :
  x, d = XD[i]
  j = bisect_left(xs, x + d) - 1
  if i == j :
    dest[i] = x + d
  else :
    dest[i] = ST.query(i, j + 1)
  ST.update(i, dest[i])

ret = 1
q = []
for i, (x, d) in enumerate(XD) :
  while q and q[0][0] <= x :
    ret += heappop(q)[1]
    ret %= mod
  heappush(q, (dest[i], ret))

while q :
  ret += heappop(q)[1]
  ret %= mod

print((ret % mod))

# Optimized solution
from bisect import bisect_left

N = int(eval(input()))
XD = [[int(i) for i in input().split()] for _ in range(N)]

mod = 998244353

XD.sort()

class SegTree:
  def __init__(self, n, v, f) :
    i = 1
    while i < n : 
      i <<= 1
    self.n = i
    self.v = v
    self.f = f
    self.tree = [v] * (i << 1)

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

  # [l, r)
  def query(self, l, r) :
    l = l + self.n
    r = r + self.n
    s = self.v
    while l < r :
      if r & 1 :
        r -= 1
        s = self.f(s, self.tree[r - 1])
      if l & 1 :
        s = self.f(s, self.tree[l - 1])
        l += 1
      l >>= 1
      r >>= 1
    return s

INF = 1 << 60
ST = SegTree(N, -INF, max)

xs = [x for x, _ in XD]
for i in range(N - 1, -1, -1) :
  x, d = XD[i]
  j = bisect_left(xs, x + d)
  ST.update(i, max(i, ST.query(i, j)))

dp = [0] * (N + 1)
dp[N] = 1

for i in range(N) :
  dp[i] += dp[i - 1]
  dp[i] %= mod
  j = ST.query(i, i + 1)
  dp[j] += dp[i - 1]
  dp[j] %= mod

print((dp[N-1]))
# Original solution
from bisect import bisect_left

N = int(eval(input()))
XD = [[int(i) for i in input().split()] for _ in range(N)]

mod = 998244353

XD.sort()

class SegTree:
  def __init__(self, n, v, f) :
    i = 1
    while i < n : 
      i <<= 1
    self.n = i
    self.v = v
    self.f = f
    self.tree = [v] * (i << 1)

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

  # [l, r)
  def query(self, l, r) :
    l = l + self.n
    r = r + self.n
    s = self.v
    while l < r :
      if r & 1 :
        r -= 1
        s = self.f(s, self.tree[r - 1])
      if l & 1 :
        s = self.f(s, self.tree[l - 1])
        l += 1
      l >>= 1
      r >>= 1
    return s

INF = 1 << 60
ST = SegTree(N, -INF, max)

xs = [x for x, _ in XD]
for i in range(N - 1, -1, -1) :
  x, d = XD[i]
  j = bisect_left(xs, x + d)
  ST.update(i, max(i, ST.query(i, j)))

dp = [0] * (N + 1)
dp[N] = 1

for i in range(N) :
  dp[i] += dp[i - 1]
  dp[i] %= mod
  j = ST.query(i, i + 1)
  dp[j] += dp[i - 1]
  dp[j] %= mod

print((dp[N-1]))

# Optimized solution
from bisect import bisect_left
import sys
input = sys.stdin.readline

N = int(eval(input()))
XD = [[int(i) for i in input().split()] for _ in range(N)]

mod = 998244353

XD.sort()

class SegTree:
  def __init__(self, n, v, f) :
    i = 1
    while i < n : 
      i <<= 1
    self.n = i
    self.v = v
    self.f = f
    self.tree = [v] * (i << 1)

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

  # [l, r)
  def query(self, l, r) :
    l = l + self.n
    r = r + self.n
    s = self.v
    while l < r :
      if r & 1 :
        r -= 1
        s = self.f(s, self.tree[r - 1])
      if l & 1 :
        s = self.f(s, self.tree[l - 1])
        l += 1
      l >>= 1
      r >>= 1
    return s

INF = 1 << 60
ST = SegTree(N, -INF, max)

xs = [x for x, _ in XD]
for i in range(N - 1, -1, -1) :
  x, d = XD[i]
  j = bisect_left(xs, x + d)
  ST.update(i, max(i, ST.query(i, j)))

dp = [0] * (N + 1)
dp[N] = 1

for i in range(N) :
  dp[i] += dp[i - 1]
  dp[i] %= mod
  j = ST.query(i, i + 1)
  dp[j] += dp[i - 1]
  dp[j] %= mod

print((dp[N-1]))
# Original solution
import sys
sys.setrecursionlimit(10 ** 7)

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

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

from bisect import bisect_left

parent = [-1] * N

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

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

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

    return res % MOD

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

print(ans)

# Optimized solution
import sys
sys.setrecursionlimit(10 ** 7)
from bisect import bisect_left

N = int(eval(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)
# Original solution
# 解説放送
# https://atcoder.jp/contests/abc158/submissions/10643692
# dfsの代わりに親の頂点番号を配列で管理する方法
# PyPyでは通った

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

    MOD = 998244353

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

    N = int(eval(input()))

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

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

        to_candidates.appendleft(robot_from)

    ret = 1
    count = [1] * N
    for robot in robots:  # x降順
        par = parents[robot.ind]
        count[robot.ind] += 1
        if ~par:
            count[par] = (count[par] * count[robot.ind]) % MOD
        else:
            ret = (ret * count[robot.ind]) % MOD
            # x降順で見ているのでpar==-1のrootのrobotを見る頃には
            # rootの子は全て見ているので安心してretにかけられる
    print(ret)
    return


if __name__ == '__main__':
    main()


# Optimized solution
def main():
    from collections import deque
    from operator import itemgetter
    import sys
    input = sys.stdin.readline

    MOD = 998244353

    N = int(eval(input()))

    xds = []
    xs = []
    for _ in range(N):
        x, d = list(map(int, input().split()))
        xds.append((x, d))
        xs.append(x)

    xds.sort(key=itemgetter(0), reverse=True)
    xs.sort()

    ps = [-1] * (N + 1)
    cands = deque()  # 既出の頂点で有向辺の行き先に設定されていないもの,x昇順
    for j, (x, d) in enumerate(xds):
        j = N - 1 - j
        while cands:
            cx, ci = cands[0]
            if x + d <= cx:
                # candは独立
                break
            elif x <= cx < x + d:
                # candと連結
                ps[ci] = j
                cands.popleft()
        cands.appendleft((x, j))

    ret = 1
    ctr = [1] * N
    for j, (x, d) in enumerate(xds):
        j = N - 1 - j
        par = ps[j]
        ctr[j] += 1  # j=off,子の総積が設定されている->j=on=1を加算
        if ~par:
            ctr[par] = ctr[par] * ctr[j] % MOD
        else:
            ret = ret * ctr[j] % MOD  # j=木のroot

    print(ret)
    return


if __name__ == '__main__':
    main()
# Original solution
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(eval(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(list(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()

# Optimized solution
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(eval(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(list(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()
# Original solution
def i1():
 return int(eval(input()))
def i2():
 return [int(i) for i in input().split()]
import bisect
mod=998244353
n=int(eval(input()))
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
    if t[i*2+1]>t[i*2+2]:t[i]=t[i*2+1]
    else:t[i]=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:
         if L<t[a]:L = t[a]
      if b&1==0:
         b-=1
         if R<t[b]:R = t[b]
      
      a>>=1
      b>>=1
      
         
    return max(L, R)
 
for i in range(n):
  d.append([int(i) for i in input().split()])
d.sort()
dx=[]
dd=[]
for i,j in d:
  dx.append(i)
  dd.append(j)
for i in range(n)[::-1]:
 tx=dx[i]+dd[i]
 j=bisect.bisect_left(dx,tx)
 tt=qr(i,j)
 if j-1>tt:ud(i,j-1)
 else: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]))

# Optimized solution
def i1():
 return int(eval(input()))
def i2():
 return [int(i) for i in input().split()]
import bisect
mod=998244353
n=int(eval(input()))
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)>>1
    if t[i*2+1]>t[i*2+2]:t[i]=t[i*2+1]
    else:t[i]=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:
         if L<t[a]:L = t[a]
      if b&1==0:
         b-=1
         if R<t[b]:R = t[b]
      
      a>>=1
      b>>=1
      
         
    return max(L, R)
 
for i in range(n):
  d.append([int(i) for i in input().split()])
d.sort()
dx=[]
dd=[]
for i,j in d:
  dx.append(i)
  dd.append(j)
for i in range(n)[::-1]:
 tx=dx[i]+dd[i]
 j=bisect.bisect_left(dx,tx)
 tt=qr(i,j)
 if j-1>tt:ud(i,j-1)
 else: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]))
# Original solution
n=int(eval(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)
#dp[n-1]=2
r=list(range(n))
r[n-1]=n-1
from bisect import bisect_left
for i in range(n):
    x,d=xd[n-1-i]
    tmp=bisect_left(aryx,x+d)
    ri=max(r[n-1-i:tmp])
    r[n-1-i]=ri
    dp[n-1-i]=dp[n-1-i+1]+dp[ri+1]
    dp[n-1-i]%=mod
print((dp[0]))


# Optimized solution
n=int(eval(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)
#dp[n-1]=2
r=list(range(n))
r[n-1]=n-1
from bisect import bisect_left

class SegmentTree:
    # 初期化処理
    # f : SegmentTreeにのせるモノイド
    # default : fに対する単位元
    def __init__(self, size, f=lambda x,y : max(x,y), default=0):
        self.size = 2**(size-1).bit_length() # 簡単のため要素数Nを2冪にする
        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]))