### BUGGY CODE ###

def init_max(init_max_val):
    #set_val
    for i in range(N):
        seg_max[i+num_max-1]=init_max_val[i]    
    #built
    for i in range(num_max-2,-1,-1) :
        seg_max[i]=max(seg_max[2*i+1],seg_max[2*i+2]) 
    
def update_max(k,x):
    k += num_max-1
    seg_max[k] = x
    while k:
        k = (k-1)//2
        seg_max[k] = max(seg_max[k*2+1],seg_max[k*2+2])
    
def query_max(p,q):
    if q<=p:
        return ide_ele_max
    p += num_max-1
    q += num_max-2
    res=ide_ele_max
    while q-p>1:
        if p&1 == 0:
            res = max(res,seg_max[p])
        if q&1 == 1:
            res = max(res,seg_max[q])
            q -= 1
        p = p//2
        q = (q-1)//2
    if p == q:
        res = max(res,seg_max[p])
    else:
        res = max(max(res,seg_max[p]),seg_max[q])
    return res

N = int(input())

#####単位元######
ide_ele_max = -1

#num_max:n以上の最小の2のべき乗
num_max =2**(N-1).bit_length()
seg_max=[ide_ele_max]*2*num_max

#sample
#n = 5
#A = [1,4,3,2,4]

#####単位元######
#ide_ele_max = -1

#num_max:n以上の最小の2のべき乗
#num_max =2**(n-1).bit_length()
#seg_max=[ide_ele_max]*2*num_max

#init
#init_max(A)

#A[1]~A[3]の最小値
#print(query_max(1,4)) #4

#A[3]を5に変更
#update_max(3,5)

#A[1]~A[3]の最小値
#print(query_max(1,4)) #5


X = [0]*N
D = [0]*N
XD = [None]*N
for i in range(N):
    X[i], D[i] = (int(i) for i in input().split())
    XD[i] = (X[i], D[i])
XD.sort()
import bisect
L = [i for i in range(N)]
init_max(L)

for i in range(N)[::-1]:
    x, d = XD[i]
    b = bisect.bisect_left(XD, (x+d-0.5, d))-1
    m = query_max(i,b+1)
    update_max(i,m)
    L[i] = m

ans = [0]*N
res = 1
for i in range(N)[::-1]:
    if L[i] == i:
        ans[i] = res
        res *= 2
    else:
        ans[i] = ans[L[i]]
        res += ans[i]
print(res)

### FIXED CODE ###

import sys
input = sys.stdin.readline

class SegmentTree(object):
 
    def __init__(self, init_array, seg_func=min, seg_func_null=10 ** 9 + 7):
 
        self.seg_func = seg_func
        self.seg_func_null = seg_func_null
        self.n = 1
        while self.n < len(init_array):
            self.n *= 2
        self.dat = [0] * (2 * self.n - 1)
        for i in range(len(init_array)):
            self.dat[self.n - 1 + i] = init_array[i]
        for i in range(self.n - 2, -1, -1):
            self.dat[i] = self.seg_func(self.dat[2 * i + 1], self.dat[2 * i + 2])
 
    def update(self, k, a):
        k += self.n - 1
        self.dat[k] = a
        while k > 0:
            k = (k - 1) // 2
            self.dat[k] = self.seg_func(self.dat[k * 2 + 1], self.dat[k * 2 + 2])
 
    def query(self, p, q):
        # [p, q)
        if q <= p:
            return self.seg_func_null
 
        p += self.n - 1
        q += self.n - 2
        res = self.seg_func_null
 
        while q - p > 1:
            if p & 1 == 0:
                res = self.seg_func(res, self.dat[p])
            if q & 1 == 1:
                res = self.seg_func(res, self.dat[q])
                q -= 1
            p = p // 2
            q = (q-1) // 2
        if p == q:
            res = self.seg_func(res, self.dat[p])
        else:
            res = self.seg_func(self.seg_func(res, self.dat[p]), self.dat[q])
 
        return res
 
N = int(input())
X = [0]*N
D = [0]*N
XD = [None]*N
for i in range(N):
    X, D = (int(i) for i in input().split())
    XD[i] = (X, D)
XD.sort()

import bisect
seg = SegmentTree(list(range(N)), max, -1)
L = list(range(N))

for i in range(N)[::-1]:
    x, d = XD[i]
    b = bisect.bisect_left(XD, (x+d-0.5, d))-1
    m = seg.query(i,b+1)
    seg.update(i,m)
    L[i] = m

ans = [0]*N
res = 1
for i in range(N)[::-1]:
    if L[i] == i:
        ans[i] = res
        res *= 2
    else:
        ans[i] = ans[L[i]]
        res += ans[i]
    res %= 998244353
print(res)