AtCoder Beginner Contest 158 - Removing Robots

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-----
2
1 5
3 3

-----Sample Output-----
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.

Source: atcoder | Difficulty: MEDIUM_HARD


Solutions:
import sys
sys.setrecursionlimit(10 ** 7)
from heapq import heappush, heappop
from collections import Counter

class HeapSet:

	def __init__(self):
		self.minQue = []
		self.maxQue = []
		self.counter = Counter()

	def insert(self, x):
		heappush(self.minQue, x)
		self.counter[x] += 1

	def erase(self, x):
		self.counter[x] -= 1

	def max(self):
		while self.maxQue and self.counter[-self.maxQue[0]] == 0:
			heappop(self.maxQue)
		return -self.maxQue[0] if self.maxQue else None

	def min(self):
		while self.minQue and self.counter[self.minQue[0]] == 0:
			heappop(self.minQue)
		return self.minQue[0] if self.minQue else None
MOD = 998244353

def resolve():

	def dfs(v):
		res = 1
		for to in to_edge[v]:
			res *= dfs(to)
			res %= MOD
		return res + 1
	N = int(input())
	AB = [tuple(map(int, input().split())) for _ in range(N)]
	AB.sort()
	st = HeapSet()
	to_edge = [[] for _ in range(N)]
	for i in range(N - 1, -1, -1):
		x = AB[i][0]
		d = AB[i][1]
		while st.min() and st.min()[0] < x + d:
			to_edge[i].append(st.min()[1])
			st.erase(st.min())
		st.insert((x, i))
	ans = 1
	for (x, v) in st.minQue:
		ans *= dfs(v)
		ans %= MOD
	print(ans)
resolve()


import sys
input = sys.stdin.readline
n = int(input())
xd = [list(map(int, input().split())) for _ in range(n)]
mod = 998244353
xd.sort()

def init_max(init_max_val):
	for i in range(n):
		seg_max[i + num_max - 1] = init_max_val[i]
	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
ide_ele_max = -1
num_max = 2 ** (len(str(bin(n - 1))) - 2)
seg_max = [ide_ele_max] * 2 * num_max
import bisect
xs = list(map(lambda x: x[0], xd))
ans = [0] * (n + 1)
ans[-1] = 1
for i in range(n - 1, -1, -1):
	move_r = bisect.bisect_left(xs, sum(xd[i]))
	if i + 1 == move_r:
		update_max(i, i)
	else:
		update_max(i, query_max(i + 1, move_r))
	ans[i] = (ans[i + 1] + ans[seg_max[i + num_max - 1] + 1]) % mod
print(ans[0])


class SegTree:

	def __init__(self, init_val, ide_ele, segfunc):
		self.n = len(init_val)
		self.num = 2 ** (self.n - 1).bit_length()
		self.ide_ele = ide_ele
		self.seg = [self.ide_ele] * 2 * self.num
		self.segfunc = segfunc
		for i in range(self.n):
			self.seg[i + self.num - 1] = init_val[i]
		for i in range(self.num - 2, -1, -1):
			self.seg[i] = 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 + 1:
			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
N = int(input())
GOTO = [i for i in range(1, N + 1)]
INF = 10 ** 15
ide_ele = -1
SEG = SegTree(GOTO, ide_ele, max)
LIST = []
XX = []
mod = 998244353
for i in range(N):
	(X, D) = map(int, input().split())
	LIST.append([X, D])
LIST.sort(key=lambda x: x[0])
for i in range(N):
	XX.append(LIST[i][0])
import bisect
for i in range(N - 1):
	j = N - 2 - i
	Xj = LIST[j][0]
	Dj = LIST[j][1]
	Nj = bisect.bisect_right(XX, Xj + Dj - 1)
	NEXT = SEG.query(j + 1, Nj)
	if NEXT != -1:
		GOTO[j] = NEXT
		SEG.update(j, NEXT)
S = [-1] * (N + 1)
S[N] = 1
for i in range(N):
	j = N - 1 - i
	S[j] = S[j + 1] + S[GOTO[j]]
	S[j] %= mod
print(S[0])


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):
		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):
		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):
		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])


def main():
	n = int(input())
	xd = [map(int, input().split()) for _ in range(n)]
	mod = 998244353
	INF = 10 ** 10
	xx = [(x, x + d, i) for (i, (x, d)) in enumerate(xd, 1)]
	xx.sort()
	adj = [[] for _ in range(n + 1)]
	stack = [(INF, 0)]
	for (l, r, i) in xx:
		while stack[-1][0] <= l:
			stack.pop()
		ip = stack[-1][1]
		adj[ip].append(i)
		stack.append((r, i))
	stack2 = [0]
	d = [-1] * (n + 1)
	d[0] = 0
	c = [[] for _ in range(n + 1)]
	order = []
	while stack2:
		u = stack2.pop()
		order.append(u)
		for v in adj[u]:
			if d[v] == -1:
				d[v] = d[u] + 1
				c[u].append(v)
				stack2.append(v)
	dp = [1] * (n + 1)
	for u in order[::-1]:
		for v in c[u]:
			dp[u] *= dp[v]
			dp[u] %= mod
		dp[u] += 1
		dp[u] %= mod
	ans = dp[0] - 1
	ans %= mod
	print(ans)
main()


law = 998244353
n = int(input())
robots = [tuple(map(int, input().split())) for _ in range(n)]
robots.sort(reverse=True)
ntrig = [-1] * n
dp = [0] * n
dp[0] = 2
for (i, (x, d)) in enumerate(robots):
	if i == 0:
		continue
	next = i - 1
	while x + d > robots[next][0]:
		next = ntrig[next]
		if next == -1:
			break
	ntrig[i] = next
	if next == -1:
		dp[i] = dp[i - 1] + 1
	else:
		dp[i] = dp[i - 1] + dp[next]
	dp[i] %= law
print(dp[n - 1])


import sys, math, itertools, collections, bisect
input = lambda : sys.stdin.buffer.readline().rstrip().decode('utf-8')
inf = float('inf')
mod = 998244353
mans = inf
ans = 0
count = 0
pro = 1
sys.setrecursionlimit(10 ** 6)
n = int(input())
XD = [(-10 ** 10, inf)]
for i in range(n):
	(x, d) = map(int, input().split())
	XD.append((x, d))
XD.sort()
visited = [0] * (n + 1)

def dfs(node):
	visited[node] = 1
	res = 1
	i = node + 1
	while i < n + 1:
		if XD[i][0] < XD[node][0] + XD[node][1]:
			if visited[i]:
				continue
			(pro, i) = dfs(i)
			res *= pro
			res %= mod
		else:
			break
	return (res + 1, i)
print((dfs(0)[0] - 1) % mod)


import sys
from operator import itemgetter
from bisect import bisect_left, bisect_right
input = sys.stdin.readline
MOD = 998244353

class SegmentTree1:

	def __init__(self, n_, ele_id, op_func):
		self.n = 1 << (n_ - 1).bit_length()
		self.data = [ele_id] * (2 * self.n)
		self.ele_id = ele_id
		self.op_func = op_func

	def __getitem__(self, i):
		return self.data[i + self.n]

	def build(self, data_init):
		for i in range(len(data_init)):
			self.data[i + self.n] = data_init[i]
		for i in reversed(range(self.n)):
			self.data[i] = self.op_func(self.data[2 * i], self.data[2 * i + 1])

	def update(self, i, x):
		i += self.n
		self.data[i] = x
		while i > 1:
			i = i >> 1
			self.data[i] = self.op_func(self.data[2 * i], self.data[2 * i + 1])

	def query(self, l, r):
		l += self.n
		r += self.n
		ret = self.ele_id
		while l < r:
			if l & 1:
				ret = self.op_func(ret, self.data[l])
				l += 1
			if r & 1:
				r -= 1
				ret = self.op_func(ret, self.data[r])
			l = l >> 1
			r = r >> 1
		return ret
n = int(input())
robot = [tuple(map(int, input().split())) for _ in range(n)]
robot.sort(key=itemgetter(0))
x = [robot[i][0] for i in range(n)]
dp = [0] * n
dp[n - 1] = n - 1
st_rmq = SegmentTree1(n, 0, max)
st_rmq.update(n - 1, dp[n - 1])
for i in reversed(range(n - 1)):
	r = bisect_left(x, x[i] + robot[i][1])
	dp[i] = max(i, st_rmq.query(l=i + 1, r=r))
	st_rmq.update(i, dp[i])
dp2 = [0] * (n + 1)
dp2[n] = 1
for i in reversed(range(n)):
	dp2[i] = dp2[i + 1] + dp2[dp[i] + 1]
	dp2[i] %= MOD
print(dp2[0])


import sys
from bisect import bisect_left
MOD = 998244353
input = sys.stdin.readline

class SegmentTree:

	def __init__(self, values, merge_func=min, default=float('inf')):
		n = len(values)
		self.size = 1
		self.default = default
		self.merge = merge_func
		while self.size < n:
			self.size *= 2
		self.tree = [self.default] * self.size * 2
		self.range = [None] * self.size * 2
		for i in range(n):
			self.tree[self.size + i] = values[i]
		for i in range(self.size):
			self.range[self.size + i] = (i, i + 1)
		for i in range(self.size - 1, 0, -1):
			self.tree[i] = self.merge(self.tree[i * 2], self.tree[i * 2 + 1])
			self.range[i] = (self.range[i * 2][0], self.range[i * 2 + 1][1])

	def get(self, index):
		return self.tree[self.size + index]

	def update(self, index, value):
		index += self.size
		self.tree[index] = value
		while index > 1:
			index //= 2
			self.tree[index] = self.merge(self.tree[index * 2], self.tree[index * 2 + 1])

	def query(self, a, b):
		q = [1]
		ret = self.default
		while len(q):
			k = q.pop()
			(l, r) = self.range[k]
			if r <= a or b <= l:
				continue
			if a <= l and r <= b:
				ret = self.merge(ret, self.tree[k])
			else:
				q.append(k * 2)
				q.append(k * 2 + 1)
		return ret

def main():
	N = int(input())
	robo = [None] * N
	for i in range(N):
		robo[i] = tuple(map(int, input().split()))
	robo.sort()
	pos = [x[0] for x in robo]
	dst = [x[0] + x[1] for x in robo]
	rmq = SegmentTree(dst, max, -float('inf'))
	for i in range(N - 1)[::-1]:
		dst[i] = rmq.query(i, bisect_left(pos, dst[i]))
		rmq.update(i, dst[i])
	dp = [0] * (N + 1)
	dp[0] = 1
	for i in range(N):
		(x, d) = robo[N - 1 - i]
		to = N - bisect_left(pos, dst[N - 1 - i])
		dp[i + 1] = (dp[i] + dp[to]) % MOD
	print(dp[N])
main()


import sys
import bisect
input = sys.stdin.readline

class SegmentTree:

	def __init__(self, a):
		self.padding = -float('inf')
		self.n = len(a)
		self.N = 2 ** (self.n - 1).bit_length()
		self.data = [self.padding] * (self.N - 1) + a + [self.padding] * (self.N - self.n)
		for i in range(2 * self.N - 2, 0, -2):
			self.data[(i - 1) // 2] = max(self.data[i], self.data[i - 1])

	def __len__(self):
		return self.n

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

	def query(self, i, j):
		if i == j:
			return self.data[self.N - 1 + i]
		else:
			idx1 = self.N - 1 + i
			idx2 = self.N - 2 + j
			result = self.padding
			while idx1 + 1 < idx2:
				if idx1 & 1 == 0:
					result = max(result, self.data[idx1])
				if idx2 & 1 == 1:
					result = max(result, self.data[idx2])
					idx2 -= 1
				idx1 //= 2
				idx2 = (idx2 - 1) // 2
			if idx1 == idx2:
				result = max(result, self.data[idx1])
			else:
				result = max(result, self.data[idx1], self.data[idx2])
			return result
MOD = 998244353
N = int(input())
XD = [list(map(int, input().split())) for i in range(N)]
XD.sort()
X = [xd[0] for xd in XD]
dp = [0] * (N + 1)
dp[-1] = 1
st = SegmentTree([i for i in range(N)])
for i in range(N - 1, -1, -1):
	idx = bisect.bisect_left(X, sum(XD[i])) - 1
	if idx > i:
		idx = st.query(i, idx + 1)
		st.update(i, idx)
	dp[i] = (dp[i + 1] + dp[idx + 1]) % MOD
print(dp[0])


import sys
from bisect import bisect_left, bisect_right
input = lambda : sys.stdin.readline()
MOD = 998244353

class SegmentTree:

	def __init__(self, n, func=lambda x, y: min(x, y), ide=float('inf')):
		self.n = 2 ** (n - 1).bit_length()
		self.data = [ide] * (self.n * 2)
		(self.func, self.ide) = (func, ide)

	def build(self, data):
		for (i, x) in enumerate(data):
			self.data[self.n + i] = x
		for i in range(self.n - 1, 0, -1):
			self.data[i] = self.func(self.data[i * 2], self.data[i * 2 + 1])

	def update(self, i, x):
		i += self.n
		self.data[i] = x
		while i > 1:
			i >>= 1
			self.data[i] = self.func(self.data[i * 2], self.data[i * 2 + 1])

	def query(self, l, r):
		l += self.n
		r += self.n
		res = self.ide
		while l < r:
			if l & 1:
				res = self.func(res, self.data[l])
				l += 1
			if r & 1:
				res = self.func(res, self.data[r - 1])
			l >>= 1
			r >>= 1
		return res

	def get(self, i):
		return self.data[self.n + i]
n = int(input())
xd = [tuple(map(int, input().split())) for _ in range(n)]
xd.sort()
(x, d) = zip(*xd)
s = SegmentTree(n, lambda x, y: max(x, y), -float('inf'))
for i in range(n)[::-1]:
	r = bisect_left(x, x[i] + d[i])
	s.update(i, max(r - 1, s.query(i, r)))
(dp1, dp2) = ([0] * n, [0] * n)
(dp1[-1], dp2[-1]) = (1, 1)
for i in range(n - 1)[::-1]:
	dp1[i] = dp1[i + 1] + dp2[i + 1] % MOD
	dp2[i] = dp1[s.get(i)]
print((dp1[0] + dp2[0]) % MOD)


import sys
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
n = int(readline())
segSize = n + 1

def init_max(init_max_val):
	for i in range(segSize):
		seg_max[i + num_max - 1] = init_max_val[i]
	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
ide_ele_max = 0
num_max = 2 ** (segSize - 1).bit_length()
seg_max = [ide_ele_max] * 2 * num_max
mod = 998244353
m = map(int, read().split())
XD = sorted(zip(m, m))
X = [x for (x, d) in XD]
from bisect import bisect_right
X = [bisect_right(X, x + d - 1) for (x, d) in XD]
init_max(list(range(segSize)))
update_max(n, n)
combs = [1] * (n + 1)
t = 0
for (x, d) in reversed(XD):
	idx = n - 1 - t
	t += 1
	p = X[idx]
	p = query_max(idx, p)
	update_max(idx, p)
	combs[idx] = (combs[p + 1] + combs[idx + 1]) % mod
print(combs[0])


import sys
import bisect
input = sys.stdin.readline
mod = 998244353

class BITree:

	def __init__(self, n):
		self.s = [-10 ** 9 - 1] * (n + 1)
		self.n = n

	def change(self, idx, val):
		while idx < self.n + 1:
			self.s[idx] = max(self.s[idx], val)
			idx += idx & -idx
		return

	def get(self, idx):
		res = -10 ** 9 - 1
		while idx > 0:
			res = max(res, self.s[idx])
			idx -= idx & -idx
		return res
n = int(input())
ans = 1
XD = []
X = []
for i in range(n):
	(x, d) = map(int, input().split())
	XD.append((x, d))
	X.append(x)
XD.sort()
X.sort()
dp = [0] * (n + 1)
dp[-1] = 1
BIT = BITree(n)
for i in range(n - 1, -1, -1):
	(x, d) = XD[i]
	will = max(x + d, BIT.get(bisect.bisect_left(X, x + d)))
	BIT.change(i + 1, will)
	dp[i] = dp[i + 1] + dp[bisect.bisect_left(X, will)]
	dp[i] %= mod
print(dp[0])


import bisect
import operator
import os
import sys
from functools import reduce

class SegmentTree:

	def __init__(self, values, op=operator.add):
		self._size = len(values)
		self._op = op
		tree = [None] * self._size * 2
		tree[self._size:] = values[:]
		for i in reversed(range(1, self._size)):
			tree[i] = self._op(tree[i << 1], tree[i << 1 | 1])
		self._tree = tree

	def set(self, i, value):
		i += self._size
		self._tree[i] = value
		i >>= 1
		while i > 0:
			self._tree[i] = self._op(self._tree[i << 1], self._tree[i << 1 | 1])
			i >>= 1

	def add(self, i, value):
		new_value = self._op(self._tree[self._size + i], value)
		self.set(i, new_value)

	def get(self, l, r=None):
		if r is None:
			return self._tree[self._size + l]
		ret_l = []
		ret_r = []
		l += self._size
		r += self._size
		while l < r:
			if l & 1:
				ret_l.append(self._tree[l])
				l += 1
			if r & 1:
				r -= 1
				ret_r.append(self._tree[r])
			l >>= 1
			r >>= 1
		return reduce(self._op, ret_l + ret_r)

	def __len__(self):
		return self._size

	def get_values_copy(self):
		return self._tree[self._size:]
if os.getenv('LOCAL'):
	sys.stdin = open('_in.txt', 'r')
sys.setrecursionlimit(10 ** 9)
INF = float('inf')
IINF = 10 ** 18
MOD = 998244353
N = int(sys.stdin.buffer.readline())
XD = [list(map(int, sys.stdin.buffer.readline().split())) for _ in range(N)]
XD.sort()
X = [x for (x, d) in XD]
D = [d for (x, d) in XD]
st = SegmentTree(list(range(N)), op=max)
for (i, (x, d)) in reversed(list(enumerate(XD))):
	ri = bisect.bisect_left(X, x + d) - 1
	st.set(i, st.get(i, ri + 1))
R = st.get_values_copy()
dp = [0] * (N + 1)
dp[-1] = 1
for (i, r) in reversed(list(enumerate(R))):
	dp[i] += dp[i + 1]
	dp[i] += dp[r + 1]
	dp[i] %= MOD
print(dp[0])


def main():
	from collections import deque, namedtuple
	from operator import attrgetter
	import sys
	sys.setrecursionlimit(10 ** 7)
	input = sys.stdin.readline
	MOD = 998244353
	Robot = namedtuple('Robot', 'x d reach ind')
	N = int(input())
	robots = []
	for ind in range(N):
		(X, D) = 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:
		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:
		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
	print(ret)
	return
main()


class SegmentTreeMax:

	def __init__(self, n, init):
		self.offset = 2 ** (n - 1).bit_length()
		self.tree = [init] * (2 * self.offset)
		self.init = init

	def update(self, pos, val):
		pos += self.offset
		self.tree[pos] = val
		while pos > 1:
			pos = pos // 2
			self.tree[pos] = max(self.tree[2 * pos], self.tree[2 * pos + 1])

	def query(self, l, r):
		l += self.offset
		r += self.offset
		ret = self.init
		while l <= r:
			ret = max(ret, self.tree[r])
			r = (r - 1) // 2
			ret = max(ret, self.tree[l])
			l = (l + 1) // 2
		return ret
mod = 998244353
n = int(input())
arr = [list(map(int, input().split())) for _ in range(n)]
arr = sorted(arr, key=lambda x: x[0])
st = SegmentTreeMax(n, 0)
ranges = []
for i in range(n):
	x = arr[i][0] + arr[i][1]
	l = -1
	r = n
	while r - l != 1:
		mid = (l + r) // 2
		if arr[mid][0] >= x:
			r = mid
		else:
			l = mid
	ranges.append(l)
	st.update(i, r)
for i in range(n - 1, -1, -1):
	ranges[i] = st.query(i, ranges[i])
	st.update(i, ranges[i])
dp = [0] * (n + 1)
dp[-1] = 1
for i in range(n - 1, -1, -1):
	j = ranges[i]
	dp[i] = dp[i + 1] + dp[j]
	dp[i] %= mod
print(dp[0])


import sys
input = sys.stdin.readline
from bisect import bisect_left

class SegTree:

	def __init__(self, a):
		self.padding = -float('inf')
		self.n = len(a)
		self.N = 2 ** (self.n - 1).bit_length()
		self.data = [self.padding] * (self.N - 1) + a + [self.padding] * (self.N - self.n)
		for i in range(2 * self.N - 2, 0, -2):
			self.data[(i - 1) // 2] = max(self.data[i], self.data[i - 1])

	def __len__(self):
		return self.n

	def __getitem__(self, key):
		return self.data[self.N - 1 + key]

	def __setitem__(self, i, value):
		self._update(i, value)

	def _update(self, i, x):
		idx = self.N - 1 + i
		self.data[idx] = x
		while idx != 0:
			idx = (idx - 1) // 2
			self.data[idx] = max(self.data[2 * idx + 1], self.data[2 * idx + 2])

	def max(self, i, j):
		if i == j:
			return self.data[self.N - 1 + i]
		else:
			idx1 = self.N - 1 + i
			idx2 = self.N - 2 + j
			result = self.padding
			while idx1 + 1 < idx2:
				if idx1 % 2 == 0:
					result = max(result, self.data[idx1])
				if idx2 % 2 == 1:
					result = max(result, self.data[idx2])
					idx2 -= 1
				idx1 //= 2
				idx2 = (idx2 - 1) // 2
			if idx1 == idx2:
				result = max(result, self.data[idx1])
			else:
				result = max(result, self.data[idx1], self.data[idx2])
			return result
n = int(input())
x_d = []
for _ in range(n):
	x_d.append(tuple(map(int, input().split())))
x_d.sort(key=lambda t: t[0])
x = [t[0] for t in x_d]
xplusd = [t[0] + t[1] for t in x_d]
shortright = [bisect_left(x, xpdi) for xpdi in xplusd]
right = SegTree([t for t in shortright])
for i in range(n - 1, -1, -1):
	right[i] = right.max(i, right[i])
dp = [None] * n
dp.append(1)
for i in range(n - 1, -1, -1):
	dp[i] = (dp[i + 1] + dp[right[i]]) % 998244353
print(dp[0])


from collections import deque
n = int(input())
info = [list(map(int, input().split())) for i in range(n)]
info = sorted(info, reverse=True)
MOD = 998244353
dp = [0] * (n + 1)
dp[0] = 1
q = deque([])
for i in range(n):
	dp[i + 1] += dp[i]
	(x, d) = info[i]
	(l, r) = (x, x + d)
	num = 1
	while True:
		if not q:
			q.append((l, num))
			break
		(tmp_l, tmp_num) = q.pop()
		if r > tmp_l:
			num = tmp_num + num
		else:
			q.append((tmp_l, tmp_num))
			q.append((l, num))
			break
	num = q[-1][1]
	dp[i + 1] += dp[i + 1 - num]
	dp[i + 1] %= MOD
print(dp[-1])


import sys
sys.setrecursionlimit(2147483647)
INF = 1 << 60
MOD = 998244353
input = lambda : sys.stdin.readline().rstrip()

class SegmentTree(object):

	def __init__(self, A, dot, unit):
		n = 1 << (len(A) - 1).bit_length()
		tree = [unit] * (2 * n)
		for (i, v) in enumerate(A):
			tree[i + n] = v
		for i in range(n - 1, 0, -1):
			tree[i] = dot(tree[i << 1], tree[i << 1 | 1])
		self._n = n
		self._tree = tree
		self._dot = dot
		self._unit = unit

	def __getitem__(self, i):
		return self._tree[i + self._n]

	def update(self, i, v):
		i += self._n
		self._tree[i] = v
		while i != 1:
			i >>= 1
			self._tree[i] = self._dot(self._tree[i << 1], self._tree[i << 1 | 1])

	def add(self, i, v):
		self.update(i, self[i] + v)

	def sum(self, l, r):
		l += self._n
		r += self._n
		l_val = r_val = self._unit
		while l < r:
			if l & 1:
				l_val = self._dot(l_val, self._tree[l])
				l += 1
			if r & 1:
				r -= 1
				r_val = self._dot(self._tree[r], r_val)
			l >>= 1
			r >>= 1
		return self._dot(l_val, r_val)
from bisect import bisect_left

def resolve():
	n = int(input())
	XD = [tuple(map(int, input().split())) for _ in range(n)]
	XD.sort()
	X = [xd[0] for xd in XD]
	tree = SegmentTree([-INF] * n, max, -INF)
	for i in range(n - 1, -1, -1):
		(x, d) = XD[i]
		j = bisect_left(X, x + d)
		tree.update(i, max(j, tree.sum(i + 1, j)))
	dp = [0] * (n + 1)
	dp[n] = 1
	for i in range(n - 1, -1, -1):
		dp[i] += dp[i + 1]
		dp[i] += dp[tree[i]]
		dp[i] %= MOD
	print(dp[0])
resolve()


import sys
sys.setrecursionlimit(10 ** 6)
from operator import itemgetter
import bisect

def main():
	input = sys.stdin.readline
	N = int(input())
	XD = [tuple(map(int, input().split())) for _ in range(N)]
	MOD = 998244353
	XD.sort(key=itemgetter(0))
	X = [xd[0] for xd in XD]
	segtree = SegmentTree(N + 1)
	for i in range(N - 1, -1, -1):
		(x, d) = XD[i]
		j = bisect.bisect_left(X, x + d, i)
		end = max(j - 1, segtree.query(i, j))
		segtree.update(i, end)
	dp = [None] * (N + 1)
	dp[N] = Mint(1, MOD)
	for i in range(N - 1, -1, -1):
		dp[i] = dp[i + 1] + dp[segtree.get(i) + 1]
	print(dp[0])

class Mint:

	def __init__(self, value=0, mod=10 ** 9 + 7):
		self.value = (value % mod + mod) % mod
		self.mod = mod

	@staticmethod
	def get_value(x):
		return x.value if isinstance(x, Mint) else x

	def inverse(self):
		(a, b) = (self.value, self.mod)
		(u, v) = (1, 0)
		while b:
			t = a // b
			(b, a) = (a - t * b, b)
			(v, u) = (u - t * v, v)
		return (u + self.mod) % self.mod

	def __repr__(self):
		return str(self.value)

	def __eq__(self, other):
		return self.value == other.val

	def __neg__(self):
		return Mint(-self.value, self.mod)

	def __hash__(self):
		return hash(self.value)

	def __bool__(self):
		return self.value != 0

	def __iadd__(self, other):
		self.value = (self.value + Mint.get_value(other)) % self.mod
		return self

	def __add__(self, other):
		new_obj = Mint(self.value, self.mod)
		new_obj += other
		return new_obj
	__radd__ = __add__

	def __isub__(self, other):
		self.value = (self.value - Mint.get_value(other) + self.mod) % self.mod
		return self

	def __sub__(self, other):
		new_obj = Mint(self.value, self.mod)
		new_obj -= other
		return new_obj

	def __rsub__(self, other):
		new_obj = Mint(Mint.get_value(other), self.mod)
		new_obj -= self
		return new_obj

	def __imul__(self, other):
		self.value = self.value * Mint.get_value(other) % self.mod
		return self

	def __mul__(self, other):
		new_obj = Mint(self.value, self.mod)
		new_obj *= other
		return new_obj
	__rmul__ = __mul__

	def __ifloordiv__(self, other):
		other = other if isinstance(other, Mint) else Mint(other, self.mod)
		self *= other.inverse
		return self

	def __floordiv__(self, other):
		new_obj = Mint(self.value, self.mod)
		new_obj //= other
		return new_obj

	def __rfloordiv__(self, other):
		new_obj = Mint(Mint.get_value(other), self.mod)
		new_obj //= self
		return new_obj

class SegmentTree:

	def __init__(self, n=None, f=max, identity_factory=int, initial_values=None):
		assert n or initial_values
		size = n if n else len(initial_values)
		d = [identity_factory() for _ in range(2 * size + 1)]
		(self.__n, self.__d, self.__f, self.__e) = (size, d, f, identity_factory)
		if initial_values:
			for (i, v) in enumerate(initial_values):
				d[size + i] = v
			for i in range(size - 1, 0, -1):
				d[i] = f(d[i << 1], d[i << 1 | 1])

	def get(self, index):
		return self.__d[index + self.__n]

	def update(self, index, value):
		(i, d, f) = (index + self.__n, self.__d, self.__f)
		if d[i] == value:
			return
		d[i] = value
		while i:
			i = i >> 1
			d[i] = f(d[i << 1], d[i << 1 | 1])

	def add(self, index, value):
		self.update(index, self.__f(self.__d[index + self.__n], value))

	def query(self, from_inclusive, to_exclusive):
		ans = self.__e()
		if to_exclusive <= from_inclusive:
			return ans
		(l, r, d, f) = (from_inclusive + self.__n, to_exclusive + self.__n, self.__d, self.__f)
		while l < r:
			if l & 1:
				(ans, l) = (f(ans, d[l]), l + 1)
			if r & 1:
				(ans, r) = (f(d[r - 1], ans), r - 1)
			(l, r) = (l >> 1, r >> 1)
		return ans

	def bisect_left(self, func):
		(i, n, f, d, v) = (1, self.__n, self.__f, self.__d, self.__e())
		while i < n:
			if func(f(v, d[i << 1])):
				(v, i) = (f(v, d[i << 1]), i << 1 | 1)
			else:
				i = i << 1
		return i - n
main()


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)
examF2()


from bisect import bisect_left
MOD = 998244353
n = int(input())
robot = []
pos = []
for i in range(n):
	(x, d) = map(int, input().split())
	robot.append([x, x + d])
	pos.append(x)
robot = sorted(robot, key=lambda y: y[0])
pos = sorted(pos)

def init(init_val):
	for i in range(n):
		MI[i + num - 1] = init_val[i]
		MA[i + num - 1] = init_val[i]
	for i in range(num - 2, -1, -1):
		MI[i] = min(MI[2 * i + 1], MI[2 * i + 2])
		MA[i] = max(MA[2 * i + 1], MA[2 * i + 2])

def update(k, x):
	k += num - 1
	MI[k] = x
	MA[k] = x
	while k + 1:
		k = (k - 1) // 2
		MI[k] = min(MI[k * 2 + 1], MI[k * 2 + 2])
		MA[k] = max(MA[k * 2 + 1], MA[k * 2 + 2])

def rangemin(p, q):
	if q <= p:
		return 1 << 100
	p += num - 1
	q += num - 2
	res = 1 << 100
	while q - p > 1:
		if p & 1 == 0:
			res = min(res, MI[p])
		if q & 1 == 1:
			res = min(res, MI[q])
			q -= 1
		p = p // 2
		q = (q - 1) // 2
	if p == q:
		res = min(res, MI[p])
	else:
		res = min(min(res, MI[p]), MI[q])
	return res

def rangemax(p, q):
	if q <= p:
		return -1
	p += num - 1
	q += num - 2
	res = -1
	while q - p > 1:
		if p & 1 == 0:
			res = max(res, MA[p])
		if q & 1 == 1:
			res = max(res, MA[q])
			q -= 1
		p = p // 2
		q = (q - 1) // 2
	if p == q:
		res = max(res, MA[p])
	else:
		res = max(max(res, MA[p]), MA[q])
	return res
num = 2 ** (n - 1).bit_length()
MI = [1 << 100] * 2 * num
MA = [-1] * 2 * num
r = []
for (x, d) in robot:
	r.append(bisect_left(pos, d))
init(r)
s = [0] * n
for x in range(n - 1, -1, -1):
	right_max = rangemax(x, r[x])
	s[x] = right_max
	update(x, right_max)
dp = [0] * (n + 1)
dp[-1] = 1
for i in range(n - 1, -1, -1):
	dp[i] = dp[i + 1] + dp[s[i]]
	dp[i] %= MOD
print(dp[0])


import sys
sys.setrecursionlimit(10 ** 7)
input = sys.stdin.readline
from bisect import bisect_left
N = int(input())
XD = [[int(i) for i in input().split()] for _ in range(N)]
XD.sort()
MOD = 998244353

def make():
	edge = [[] for _ in range(N)]
	parent = [-1] * N
	MAXIDX = N
	sorted_X = [X for (X, _) in XD]
	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)
	return (parent, edge)
(parent, edge) = make()

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

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

def __starting_point():
	main()
__starting_point()


import numpy as np
M = 998244353
n = int(input())
xs = [0] * n
ds = [0] * n
for i in range(n):
	(x, d) = (int(c) for c in input().split())
	ds[i] = d
	xs[i] = x
xs = np.array(xs)
ds = np.array(ds)
import sys
sys.setrecursionlimit(max(1000, n))
index = xs.argsort()
xs = xs[index]
ds = ds[index]

def _sub(i):
	if i == n - 1:
		return (2, n)
	res = 1
	ind = i + 1
	while True:
		if xs[i] + ds[i] <= xs[ind]:
			break
		(o, ind) = _sub(ind)
		res *= o
		res %= M
		if ind >= n:
			break
	return (res + 1, ind)
out = []
done = 0
while True:
	(o, done) = _sub(done)
	out.append(o)
	if done >= n:
		break
result = 1
for o in out:
	result *= o
	result %= M
print(result)


import bisect

class SegTree:

	def __init__(self, n):
		self.n = n
		self.s = 1
		while self.s < self.n:
			self.s <<= 1
		self.mins = [1 << 30] * (self.s * 2)

	def update(self, i, val):
		i += self.s
		self.mins[i] = val
		i >>= 1
		while i:
			self.mins[i] = min(self.mins[i * 2], self.mins[i * 2 + 1])
			i >>= 1

	def min(self, l, r):
		l += self.s
		r += self.s
		res = self.mins[0]
		while l <= r:
			if l & 1:
				res = min(res, self.mins[l])
				l += 1
			if not r & 1:
				res = min(res, self.mins[r])
				r -= 1
			l >>= 1
			r >>= 1
		return res
MOD = 998244353
N = int(input())
robots = []
for _ in range(N):
	(x, d) = map(int, input().split())
	robots.append((-x, -d))
robots.sort()
dp = [0] * (N + 1)
dp[0] = 1
st = SegTree(N)
for (i, (x, d)) in enumerate(robots):
	lo = bisect.bisect_right(robots, (x + d, 0), hi=i)
	lo = min(lo, st.min(lo, i))
	st.update(i, lo)
	dp[i + 1] += (dp[i] + dp[lo]) % MOD
print(dp[-1])


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):
		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)


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)
main()


from collections import defaultdict, deque
from heapq import heappush, heappop
from itertools import permutations
import sys
import math
import bisect

def LI():
	return [int(x) for x in sys.stdin.readline().split()]

def I():
	return int(sys.stdin.readline())

def LS():
	return [list(x) for x in sys.stdin.readline().split()]

def S():
	res = list(sys.stdin.readline())
	if res[-1] == '\n':
		return res[:-1]
	return res

def IR(n):
	return [I() for i in range(n)]

def LIR(n):
	return [LI() for i in range(n)]

def SR(n):
	return [S() for i in range(n)]

def LSR(n):
	return [LS() for i in range(n)]
sys.setrecursionlimit(1000000)
mod = 998244353
import operator

class SegmentTree:

	def __init__(self, size, default, f=operator.add):
		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 add(self, i, x):
		i += self.size
		self.dat[i] = self.f(self.dat[i], x)
		while i > 0:
			i >>= 1
			self.dat[i] = self.f(self.dat[i], x)

	def get(self, a, b=None):
		if b is None:
			b = a + 1
		(l, r) = (a + self.size, b + 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

def solve():
	n = I()
	a = LIR(n)
	a.sort()
	ans = [None] * (n + 1)
	s = SegmentTree(n, 0, max)
	ans[n] = 1
	X = [i[0] for i in a]
	for i in range(n)[::-1]:
		(x, d) = a[i]
		k = x + d
		j = bisect.bisect_left(X, k)
		b = s.get(i, j)
		if j < b:
			j = b
		s.update(i, j)
		ans[i] = ans[j] + ans[i + 1]
		ans[i] %= mod
	print(ans[0])
	return
solve()


import sys
input = sys.stdin.buffer.readline
from collections import defaultdict
import bisect
con = 998244353
INF = float('inf')

def getlist():
	return list(map(int, input().split()))

class SegmentTree(object):

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

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

	def query(self, l, r):
		L = l + self.N0
		R = r + self.N0 + 1
		m = 0
		while L < R:
			if R & 1:
				R -= 1
				m = max(m, self.data[R - 1])
			if L & 1:
				m = max(m, self.data[L - 1])
				L += 1
			L >>= 1
			R >>= 1
		return m

def main():
	N = int(input())
	XD = [None] * N
	for i in range(N):
		(X, D) = getlist()
		XD[i] = [X, D]
	XD.sort()
	Xl = [XD[i][0] for i in range(N)]
	Xl.append(INF)
	Seg = SegmentTree(N)
	IND = [None] * N
	for i in range(N):
		ind = bisect.bisect_left(Xl, XD[i][0] + XD[i][1]) - 1
		Seg.update(i, ind)
		IND[i] = ind
	DP = [[0] for i in range(N + 1)]
	DP[N] = 1
	for i in range(N - 1, -1, -1):
		ind = Seg.query(i, IND[i])
		Seg.update(i, ind)
		DP[i] = DP[i + 1] + DP[ind + 1]
		DP[i] %= con
	ans = DP[0]
	print(ans)
main()


import sys
sys.setrecursionlimit(10 ** 9)
MOD = 998244353
N = int(input())
robo = list((list(map(int, input().split())) for i in range(N)))
robo.sort()
child = [[] for i in range(N + 1)]
stack = []
for i in range(N):
	(x, d) = robo[i]
	while stack and stack[-1][0] <= x:
		stack.pop()
	if stack:
		child[stack[-1][1]].append(i + 1)
	else:
		child[0].append(i + 1)
	stack.append([x + d, i + 1])

def func(x):
	hoge = 1
	for i in child[x]:
		hoge *= func(i)
		hoge %= MOD
	return (hoge + 1) % MOD
print(func(0) - 1)


class SegTree:

	def __init__(self, init_val, ide_ele, seg_func):
		self.segfunc = seg_func
		n = len(init_val)
		self.num = 2 ** (n - 1).bit_length()
		self.ide_ele = ide_ele
		self.seg = [self.ide_ele] * 2 * self.num
		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 + 1:
			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
import sys
input = sys.stdin.readline
mod = 998244353
N = int(input())
X = []
Y = []
for _ in range(N):
	(x, d) = map(int, input().split())
	X.append((x, d))
X.sort(key=lambda x: x[0])
for (i, (x, d)) in enumerate(X):
	Y.append((2 * x, i, 0))
	Y.append((2 * x + 2 * d - 1, i, 1))
Y.sort(key=lambda x: x[0])
C = [0] * N
for (x, i, t) in Y:
	if t == 0:
		j = i
	elif t == 1:
		C[i] = j
st = SegTree(C, -1, max)
dp = [1] * (N + 1)
for i in range(N - 1, -1, -1):
	y = st.query(i, C[i] + 1)
	st.update(i, y)
	dp[i] = (dp[i + 1] + dp[y + 1]) % mod
print(dp[0])


import bisect
import sys
stdin = sys.stdin
ni = lambda : int(ns())
na = lambda : list(map(int, stdin.readline().split()))
ns = lambda : stdin.readline().rstrip()
n = ni()
co = []
for i in range(n):
	co.append(na())
	co[-1][1] += co[-1][0]
co.sort(key=lambda x: x[0])

class Segtreermq:

	def __init__(self, n):
		self.H = 1
		while self.H < n:
			self.H *= 2
		self.M = self.H * 2
		self.vals = [999999999999] * self.M

	def update(self, pos, v):
		self.vals[self.H + pos] = v
		x = self.H + pos >> 1
		while x >= 1:
			self.vals[x] = min(self.vals[2 * x], self.vals[2 * x + 1])
			x >>= 1

	def min(self, l, r):
		ret = 999999999999999
		if l >= r:
			return ret
		while l != 0:
			f = l & -l
			if l + f > r:
				break
			v = self.vals[(self.H + l) // f]
			if v < ret:
				ret = v
			l += f
		while l < r:
			f = r & -r
			v = self.vals[(self.H + r) // f - 1]
			if v < ret:
				ret = v
			r -= f
		return ret
xs = [_[0] for _ in co]
st = Segtreermq(n)
for i in range(n - 1, -1, -1):
	ind = bisect.bisect_left(xs, co[i][1])
	reach = max(co[i][1], -st.min(i, ind))
	st.update(i, -reach)
	co[i][1] = reach
mod = 998244353
stack = []
dp = [0] * n
for i in range(n - 1, -1, -1):
	val = 1
	while len(stack) > 0 and co[stack[-1]][1] <= co[i][1]:
		val = val * dp[stack[-1]] % mod
		stack.pop(-1)
	dp[i] = (val + 1) % mod
	stack.append(i)
ans = 1
for s in stack:
	ans = ans * dp[s] % mod
print(ans)


n = int(input())
x = [list(map(int, input().split())) for i in range(n)] + [[10 ** 10]]
x.sort(key=lambda x: x[0])
a = [0] * (n - 1)
y = a + [n]
a += [2, 1]
for i in range(n - 2, -1, -1):
	y[i] = i + 1
	while x[y[i]][0] < sum(x[i]):
		y[i] = y[y[i]]
	a[i] = (a[i + 1] + a[y[i]]) % 998244353
print(a[0])


printn = lambda x: print(x, end='')
inn = lambda : int(input())
inl = lambda : list(map(int, input().split()))
inm = lambda : map(int, input().split())
ins = lambda : input().strip()
DBG = True and False
BIG = 10 ** 18
R = 998244353

def ddprint(x):
	if DBG:
		print(x)

class Segtree:

	def __init__(s, l, unit, oper):
		s.unit = unit
		s.oper = oper
		s.n = 1
		while s.n < l:
			s.n *= 2
		s.ary = [s.unit for i in range(2 * s.n - 1)]

	def get(s, i):
		return s.ary[i + s.n - 1]

	def set(s, i, v):
		k = i + s.n - 1
		s.ary[k] = v
		while k > 0:
			k = (k - 1) // 2
			s.ary[k] = s.oper(s.ary[2 * k + 1], s.ary[2 * k + 2])

	def setary(s, a):
		for (i, v) in enumerate(a):
			s.ary[i + s.n - 1] = v
		for k in range(s.n - 2, -1, -1):
			s.ary[k] = s.oper(s.ary[2 * k + 1], s.ary[2 * k + 2])

	def query(s, x, y):
		l = x + s.n - 1
		r = y + s.n - 1
		res = s.unit
		while l < r:
			if not l % 2:
				res = s.oper(res, s.ary[l])
				l += 1
			if not r % 2:
				r -= 1
				res = s.oper(res, s.ary[r])
			l >>= 1
			r >>= 1
		return res
from bisect import bisect_left
n = inn()
xd = []
for i in range(n):
	(xx, dd) = inm()
	xd.append((xx, dd))
xd.sort()
x = [xd[i][0] for i in range(n)]
r = [i for i in range(n)]
sgt = Segtree(n, 0, max)
sgt.setary(r)
f = [0] * (n + 1)
f[n] = 1
f[n - 1] = 2
for i in range(n - 2, -1, -1):
	(xx, dd) = xd[i]
	j = bisect_left(x, xx + dd)
	k = sgt.query(i, j)
	sgt.set(i, k)
	f[i] = (f[i + 1] + f[k + 1]) % R
print(f[0])


def main():
	import sys
	sys.setrecursionlimit(10 ** 9)
	input = sys.stdin.readline
	mod = 998244353
	N = int(input())
	robot = [tuple(map(int, input().split())) for _ in range(N)]
	robot.sort()
	stack = []
	dp = [1] * (N + 1)
	for i in reversed(range(N)):
		(x, d) = robot[i]
		while stack and robot[stack[-1]][0] < x + d:
			stack.pop()
		if stack:
			dp[i] = dp[i + 1] + dp[stack[-1]]
		else:
			dp[i] = dp[i + 1] + 1
		dp[i] %= mod
		stack.append(i)
	print(dp[0])
main()


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) + 1
	robots.sort()
	parent = [None] * N
	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
	for i in reversed(range(1, N)):
		p = parent[i]
		dp[p] *= dp[i] + 1
		dp[p] %= MOD
	return dp[0]
N = int(input())
robots = [tuple(map(int, input().split())) for _ in range(N)]
print(solve(robots))


mod = 998244353
from bisect import bisect_left
from operator import itemgetter
N = int(input())
xd = [list(map(int, input().split())) for _ in range(N)]
xd.sort(key=itemgetter(0))
X = [xd[i][0] for i in range(N)]
D = [xd[i][1] for i in range(N)]
N0 = 2 ** (N - 1).bit_length()
INF = 2 ** 31 - 1
data = [INF] * (4 * N0)

def update(k, x):
	k += N0 - 1
	data[k] = x
	while k >= 0:
		k = (k - 1) // 2
		data[k] = min(data[2 * k + 1], data[2 * k + 2])

def query(l, r):
	L = l + N0
	R = r + N0
	s = INF
	while L < R:
		if R & 1:
			R -= 1
			s = min(s, data[R - 1])
		if L & 1:
			s = min(s, data[L - 1])
			L += 1
		L >>= 1
		R >>= 1
	return s
for i in range(N - 1, -1, -1):
	j = bisect_left(X, X[i] + D[i])
	update(i, -i)
	update(i, query(i, j))
dp = [0] * (N + 1)
dp[-1] = 1
for i in range(N - 1, -1, -1):
	dp[i] += dp[i + 1]
	dp[i] += dp[-query(i, i + 1) + 1]
	dp[i] %= mod
print(dp[0])


from bisect import bisect_left, bisect_right
import sys
input = sys.stdin.readline

def solve():
	MOD = 998244353
	INF = float('inf')
	N = int(input())
	XDs = [tuple(map(int, input().split())) for _ in range(N)] + [(10 ** 12, 0)]
	XDs.sort()
	Xs = [X for (X, D) in XDs]

	def max2(x, y):
		return x if x >= y else y

	def makeBIT(numEle):
		numPow2 = 2 ** (numEle - 1).bit_length()
		data = [-INF] * (numPow2 + 1)
		return (data, numPow2)

	def setInit(As):
		for (iB, A) in enumerate(As, 1):
			data[iB] = A
		for iB in range(1, numPow2):
			i = iB + (iB & -iB)
			data[i] = max2(data[i], data[iB])

	def setValue(iA, A):
		iB = iA + 1
		while iB <= numPow2:
			data[iB] = max2(data[iB], A)
			iB += iB & -iB

	def getMax(iA):
		iB = iA + 1
		ans = -INF
		while iB > 0:
			ans = max2(ans, data[iB])
			iB -= iB & -iB
		return ans
	(data, numPow2) = makeBIT(N + 1)
	setInit(list(range(N)))
	dp = [0] * (N + 1)
	dp[-1] = 1
	for i in reversed(range(N)):
		(X, D) = XDs[i]
		j = bisect_left(Xs, X + D) - 1
		pos = getMax(j)
		setValue(i, pos)
		dp[i] = dp[pos + 1] + dp[i + 1]
		dp[i] %= MOD
	print(dp[0])
solve()


import sys
input = sys.stdin.readline
import bisect
MOD = 998244353
n = int(input())
xd = []
places = [(10 ** 12, 0)]
for _ in range(n):
	(x, d) = [int(item) for item in input().split()]
	xd.append((x, d))
xd.sort(reverse=True)
affect = [0] * (n + 1)
dp = [0] * (n + 1)
dp[0] = 1
for (i, (x, d)) in enumerate(xd):
	frm = x
	too = x + d
	too_idx = i
	while too > places[-1][0]:
		(_, too_idx) = places.pop()
	places.append((frm, too_idx))
	dp[i + 1] = dp[i] + dp[too_idx]
	dp[i + 1] %= MOD
print(dp[-1])


import bisect
n = int(input())
x = []
d = []
mod = 998244353
l = []
for i in range(n):
	l.append(list(map(int, input().split())))
l.sort(key=lambda x: x[0])
for i in range(n):
	(a, b) = (l[i][0], l[i][1])
	x.append(a)
	d.append(b)
r = [0] * n
r[-1] = n - 1
for i in range(n - 2, -1, -1):
	xi = bisect.bisect_left(x, x[i] + d[i])
	xi -= 1
	r[i] = xi

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

def init(init_val):
	for i in range(n):
		seg[i + num - 1] = init_val[i]
	for i in range(num - 2, -1, -1):
		seg[i] = segfunc(seg[2 * i + 1], seg[2 * i + 2])

def update(k, x):
	k += num - 1
	seg[k] = x
	while k + 1:
		k = (k - 1) // 2
		seg[k] = segfunc(seg[k * 2 + 1], seg[k * 2 + 2])

def query(p, q):
	if q <= p:
		return ide_ele
	p += num - 1
	q += num - 2
	res = ide_ele
	while q - p > 1:
		if p & 1 == 0:
			res = segfunc(res, seg[p])
		if q & 1 == 1:
			res = segfunc(res, seg[q])
			q -= 1
		p = p // 2
		q = (q - 1) // 2
	if p == q:
		res = segfunc(res, seg[p])
	else:
		res = segfunc(segfunc(res, seg[p]), seg[q])
	return res
ide_ele = -10
num = 2 ** (n - 1).bit_length()
seg = [ide_ele] * 2 * num
init(r)
rr = [0] * n
rr[-1] = n - 1
for i in range(n - 2, -1, -1):
	rr[i] = query(i, r[i] + 1)
	update(i, rr[i])
dp = [0] * (n + 1)
dp[-2] = 2
dp[-1] = 1
for i in range(n - 2, -1, -1):
	dp[i] = (dp[i + 1] + dp[rr[i] + 1]) % mod
print(dp[0] % mod)


class segment_tree:

	def __init__(self, N, operator_M, e_M):
		self.op_M = operator_M
		self.e_M = e_M
		self.N0 = 1 << (N - 1).bit_length()
		self.dat = [self.e_M] * (2 * self.N0)

	def build(self, initial):
		self.dat[self.N0:self.N0 + len(initial)] = initial[:]
		for k in range(self.N0 - 1, 0, -1):
			self.dat[k] = self.op_M(self.dat[2 * k], self.dat[2 * k + 1])

	def update(self, k, x):
		k += self.N0
		self.dat[k] = x
		k //= 2
		while k:
			self.dat[k] = self.op_M(self.dat[2 * k], self.dat[2 * k + 1])
			k //= 2

	def query(self, L, R):
		L += self.N0
		R += self.N0 + 1
		sl = sr = self.e_M
		while L < R:
			if R & 1:
				R -= 1
				sr = self.op_M(self.dat[R], sr)
			if L & 1:
				sl = self.op_M(sl, self.dat[L])
				L += 1
			L >>= 1
			R >>= 1
		return self.op_M(sl, sr)

	def get(self, k):
		return self.dat[k + self.N0]
import sys
sys.setrecursionlimit(10 ** 6)
readline = sys.stdin.readline
read = sys.stdin.read
n = int(input())
xd = [[int(i) for i in readline().split()] for _ in range(n)]
xd.sort(key=lambda x: x[0])
xx = [xdi[0] for xdi in xd]
from bisect import bisect_left
a = [bisect_left(xx, x + d) - 1 for (x, d) in xd]
seg = segment_tree(n, max, 0)
seg.build(a)
b = list(range(n))
for i in range(n - 2, -1, -1):
	if i + 1 <= a[i]:
		b[i] = seg.query(i + 1, a[i])
		seg.update(i, b[i])
dp = [0] * (n + 1)
dp[-1] = 1
MOD = 998244353
for i in range(n - 1, -1, -1):
	dp[i] = (dp[i + 1] + dp[b[i] + 1]) % MOD
print(dp[0])


import bisect

def segfunc(x, y):
	return max(x, y)
ide_ele = -10000000000

class SegTree:

	def __init__(self, init_val, segfunc, ide_ele):
		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 += 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):
		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])


M = 998244353
n = int(input())
r = []
for i in range(n):
	(x, d) = map(int, input().split())
	r.append((x, x + d))
r.sort()
cls = []
dp = [0 for i in range(n + 1)]
dp[n] = 1
for i in range(n - 1, -1, -1):
	ne = i + 1
	while cls:
		(ci, cne) = cls[-1]
		if r[ci][0] < r[i][1]:
			cls.pop()
			ne = cne
		else:
			break
	cls.append((i, ne))
	dp[i] = (dp[i + 1] + dp[ne]) % M
print(dp[0])


from heapq import heappush, heappop
import sys
input = sys.stdin.readline
mod = 998244353
N = int(input())
XD = [tuple(map(int, input().split())) for _ in range(N)]
XD.sort(key=lambda x: x[0])
children = [[] for _ in range(N)]
pq = []
for (i, (x, d)) in list(enumerate(XD))[::-1]:
	while pq and pq[0][0] < x + d:
		(y, j) = heappop(pq)
		children[i].append(j)
	heappush(pq, (x, i))
val = [0] * N
for i in range(N)[::-1]:
	res = 1
	for j in children[i]:
		res = res * val[j] % mod
	val[i] = res + 1
ans = 1
while pq:
	(x, i) = heappop(pq)
	ans = ans * val[i] % mod
print(ans)


from collections import defaultdict, deque, Counter
from heapq import heappush, heappop, heapify
from bisect import bisect_right, bisect_left
import random
from itertools import permutations, accumulate, combinations, product
import sys
import string
from bisect import bisect_left, bisect_right
from math import factorial, ceil, floor, gamma, log
from operator import mul
from functools import reduce
from copy import deepcopy
sys.setrecursionlimit(2147483647)
INF = 10 ** 20

def LI():
	return list(map(int, sys.stdin.buffer.readline().split()))

def I():
	return int(sys.stdin.buffer.readline())

def LS():
	return sys.stdin.buffer.readline().rstrip().decode('utf-8').split()

def S():
	return sys.stdin.buffer.readline().rstrip().decode('utf-8')

def IR(n):
	return [I() for i in range(n)]

def LIR(n):
	return [LI() for i in range(n)]

def SR(n):
	return [S() for i in range(n)]

def LSR(n):
	return [LS() for i in range(n)]

def SRL(n):
	return [list(S()) for i in range(n)]

def MSRL(n):
	return [[int(j) for j in list(S())] for i in range(n)]
mod = 998244353

class Segtree:

	def __init__(self, A, ide_ele, segfunc, initialize=True):
		self.n = len(A)
		self.size = 2 ** (self.n - 1).bit_length()
		self.ide_ele = ide_ele
		self.segfunc = segfunc
		if initialize:
			self.data = [ide_ele] * self.size + A + [ide_ele] * (self.size - self.n)
			for i in range(self.size - 1, 0, -1):
				self.data[i] = self.segfunc(self.data[2 * i], self.data[2 * i + 1])
		else:
			self.data = [ide_ele] * (2 * self.size)

	def update(self, k, x):
		k += self.size
		self.data[k] = x
		while k:
			k = k >> 1
			self.data[k] = self.segfunc(self.data[2 * k], self.data[2 * k + 1])

	def query(self, l, r):
		(L, R) = (l + self.size, r + self.size)
		s = self.ide_ele
		while L < R:
			if R & 1:
				R -= 1
				s = self.segfunc(s, self.data[R])
			if L & 1:
				s = self.segfunc(s, self.data[L])
				L += 1
			L >>= 1
			R >>= 1
		return s
n = I()
XD = sorted(LIR(n))
X = []
D = []
for (x, d) in XD:
	X += [x]
	D += [d]
last = [l for l in range(n)]
st = Segtree(last, -INF, max)
for i in range(n - 2, -1, -1):
	r = bisect_left(X, X[i] + D[i])
	ret = st.query(i, r)
	st.update(i, ret)
	last[i] = ret
dp = [1] * (n + 1)
for j in range(n - 1, -1, -1):
	k = last[j]
	dp[j] = (dp[j + 1] + dp[k + 1]) % mod
print(dp[0])


def main():
	from collections import deque
	import sys
	sys.setrecursionlimit(10 ** 7)
	input = sys.stdin.readline
	n = int(input())
	X = sorted([list(map(int, input().split())) for i in range(n)])
	mod = 998244353
	e = [[] for i in range(n)]

	def dfs(x):
		count = 1
		for i in e[x]:
			count *= dfs(i)
			count %= mod
		return count + 1
	q = deque([])
	for i in range(n - 1, -1, -1):
		(a, b) = X[i]
		while q and q[0][0] < a + b:
			e[i].append(q[0][1])
			q.popleft()
		q.appendleft([a, i])
	ans = 1
	for (i, j) in q:
		ans *= dfs(j)
		ans %= mod
	print(ans)
main()


import sys
input = sys.stdin.readline

def solve():
	MOD = 998244353
	N = int(input())
	XDs = [tuple(map(int, input().split())) for _ in range(N)] + [(10 ** 12, 0)]
	XDs.sort()
	Xs = [X for (X, D) in XDs]
	stack = [N]
	dp = [0] * (N + 1)
	dp[-1] = 1
	for i in reversed(list(range(N))):
		(X, D) = XDs[i]
		while Xs[stack[-1]] < X + D:
			stack.pop()
		dp[i] = dp[stack[-1]] + dp[i + 1]
		dp[i] %= MOD
		stack.append(i)
	print(dp[0])
solve()


def bisect(pos):
	l = -1
	r = n
	while r - l != 1:
		mid = (l + r) // 2
		if arr[mid][0] >= pos:
			r = mid
		else:
			l = mid
	return r
mod = 998244353
n = int(input())
arr = [list(map(int, input().split())) for _ in range(n)]
arr = sorted(arr, key=lambda x: x[0])
poss = []
for i in range(n):
	poss.append(bisect(arr[i][0] + arr[i][1]))
poss.append(n)
offset = 2 ** (n - 1).bit_length()
st = [0] * (2 * offset)

def update(pos, x):
	pos += offset
	st[pos] = x
	while pos > 1:
		y = st[pos ^ 1]
		if x <= y:
			break
		pos >>= 1
		st[pos] = x

def get_max(l, r):
	ret = 0
	l += offset
	r += offset
	while l < r:
		if r & 1:
			ret = max(ret, st[r - 1])
		if l & 1:
			ret = max(ret, st[l])
			l += 1
		l >>= 1
		r >>= 1
	return ret
for i in range(n):
	update(i, poss[i])
for i in range(n - 1, -1, -1):
	poss[i] = get_max(i, poss[i])
	update(i, poss[i])
dp = [0] * (n + 1)
dp[-1] = 1
for i in range(n - 1, -1, -1):
	dp[i] += dp[i + 1]
	dp[i] %= mod
	pos = poss[i]
	dp[i] += dp[pos]
	dp[i] %= mod
print(dp[0] % mod)


def main():
	from collections import deque
	from operator import itemgetter
	import sys
	input = sys.stdin.readline
	MOD = 998244353
	N = int(input())
	xds = []
	xs = []
	for _ in range(N):
		(x, d) = 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()
	for (j, (x, d)) in enumerate(xds):
		j = N - 1 - j
		while cands:
			(cx, ci) = cands[0]
			if x + d <= cx:
				break
			elif x <= cx < x + d:
				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
		if ~par:
			ctr[par] = ctr[par] * ctr[j] % MOD
		else:
			ret = ret * ctr[j] % MOD
	print(ret)
	return
main()


from bisect import bisect_left
import sys
input = sys.stdin.readline
N = int(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])

	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])


import sys
readline = sys.stdin.readline
MOD = 998244353

class Segtree:

	def __init__(self, A, intv, initialize=True, segf=max):
		self.N = len(A)
		self.N0 = 2 ** (self.N - 1).bit_length()
		self.intv = intv
		self.segf = segf
		if initialize:
			self.data = [intv] * self.N0 + A + [intv] * (self.N0 - self.N)
			for i in range(self.N0 - 1, 0, -1):
				self.data[i] = self.segf(self.data[2 * i], self.data[2 * i + 1])
		else:
			self.data = [intv] * (2 * self.N0)

	def update(self, k, x):
		k += self.N0
		self.data[k] = x
		while k > 0:
			k = k >> 1
			self.data[k] = self.segf(self.data[2 * k], self.data[2 * k + 1])

	def query(self, l, r):
		(L, R) = (l + self.N0, r + self.N0)
		s = self.intv
		while L < R:
			if R & 1:
				R -= 1
				s = self.segf(s, self.data[R])
			if L & 1:
				s = self.segf(s, self.data[L])
				L += 1
			L >>= 1
			R >>= 1
		return s

	def binsearch(self, l, r, check, reverse=False):
		(L, R) = (l + self.N0, r + self.N0)
		(SL, SR) = ([], [])
		while L < R:
			if R & 1:
				R -= 1
				SR.append(R)
			if L & 1:
				SL.append(L)
				L += 1
			L >>= 1
			R >>= 1
		if reverse:
			for idx in SR + SL[::-1]:
				if check(self.data[idx]):
					break
			else:
				return -1
			while idx < self.N0:
				if check(self.data[2 * idx + 1]):
					idx = 2 * idx + 1
				else:
					idx = 2 * idx
			return idx - self.N0
		else:
			for idx in SL + SR[::-1]:
				if check(self.data[idx]):
					break
			else:
				return -1
			while idx < self.N0:
				if check(self.data[2 * idx]):
					idx = 2 * idx
				else:
					idx = 2 * idx + 1
			return idx - self.N0
N = int(readline())
XD = [tuple(map(int, readline().split())) for _ in range(N)]
XD.sort(key=lambda x: (x[0], -x[1]))
sXD = []
seen = set()
for (x, d) in XD:
	if x not in seen:
		sXD.append((x, d))
		seen.add(x)
N = len(sXD)
table = list(range(N))
T = Segtree(table, -1, initialize=True, segf=max)
(X, D) = map(list, zip(*sXD))
for i in range(N - 1, -1, -1):
	ok = i
	ng = N
	gi = X[i] + D[i]
	while abs(ok - ng) > 1:
		med = (ok + ng) // 2
		if X[med] < gi:
			ok = med
		else:
			ng = med
	table[i] = T.query(i, ok + 1)
	T.update(i, table[i])
dp = [0] * (N + 1)
dp[N] = 1
Dp = dp[:]
for i in range(N - 1, -1, -1):
	dp[i] = Dp[table[i] + 1]
	Dp[i] = (Dp[i + 1] + dp[i]) % MOD
print(Dp[0])


MOD = 998244353
N = int(input())
robots = []
for _ in range(N):
	(x, d) = map(int, input().split())
	robots.append((x, d))
robots.sort(reverse=True)
dp = [0] * (N + 1)
los = [N] * (N + 1)
dp[0] = 1
los[0] = 0
for (i, (x, d)) in enumerate(robots):
	lo = i
	while lo > 0 and robots[lo - 1][0] < x + d:
		lo = los[lo]
	los[i + 1] = lo
	dp[i + 1] += (dp[i] + dp[lo]) % MOD
print(dp[-1])


import sys
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
readlines = sys.stdin.buffer.readlines
from bisect import bisect_left
MOD = 998244353
N = int(readline())
m = map(int, read().split())
XD = sorted(zip(m, m))
(X, D) = zip(*XD)

class MaxSegTree:

	def __init__(self, raw_data):
		N = len(raw_data)
		self.size = 1 << N.bit_length()
		self.data = [0] * (2 * self.size)
		self.build(raw_data)

	def build(self, raw_data):
		for (i, x) in enumerate(raw_data):
			self.data[self.size + i] = x
		for i in range(self.size - 1, 0, -1):
			x = self.data[i + i]
			y = self.data[i + i + 1]
			self.data[i] = x if x > y else y

	def update(self, i, x):
		i += self.size
		self.data[i] = x
		i >>= 1
		while i:
			x = self.data[i + i]
			y = self.data[i + i + 1]
			self.data[i] = x if x > y else y
			i >>= 1

	def get_data(self, i):
		return self.data[i + self.size]

	def get_max(self, L, R):
		L += self.size
		R += self.size + 1
		x = 0
		while L < R:
			if L & 1:
				y = self.data[L]
				if x < y:
					x = y
				L += 1
			if R & 1:
				R -= 1
				y = self.data[R]
				if x < y:
					x = y
			L >>= 1
			R >>= 1
		return x
R = [0] + [bisect_left(X, x + d) for (x, d) in XD]
seg = MaxSegTree(R)
S = [0] * len(R)
for n in range(N, 0, -1):
	r = R[n]
	x = seg.get_max(n, r)
	S[n] = x
	seg.update(n, x)
dp = [0] * (N + 1)
dp[0] = 1
dp_cum = [1] * (N + 1)
for (n, r) in enumerate(S[1:], 1):
	dp[r] += dp_cum[n - 1]
	dp[r] %= MOD
	dp_cum[n] = dp_cum[n - 1] + dp[n]
	dp_cum[n] %= MOD
print(dp_cum[-1])


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])


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])


N = int(input())
(R, d, f, s, x) = (sorted((list(map(int, input().split())) for i in range(N))) + [(2000000000.0, 0)], [0] * N + [1], [0] * N, 1, N)
for i in range(N - 1, -1, -1):
	while R[x][0] < sum(R[i]):
		x = f[x]
	d[i] = s = (s + d[x]) % 998244353
	(f[i], x) = (x, i)
print(d[0])


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])


import sys
from bisect import bisect_left as bl
input = sys.stdin.readline
N = int(input())
mod = 998244353
a = []
xs = [0] * N
for _ in range(N):
	(x, d) = map(int, input().split())
	a.append((x, d))
a.sort()
for i in range(N):
	xs[i] = a[i][0]

class SegTree:

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

	def __init__(self, n, ide_ele, init_val):
		self.ide_ele = ide_ele
		self.num = 2 ** (n - 1).bit_length()
		self.seg = [self.ide_ele] * 2 * self.num
		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 + 1:
			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
seg = SegTree(N, 0, [0] * N)
for l in range(N - 1, -1, -1):
	r = bl(xs, a[l][0] + a[l][1])
	mx = max(l, seg.query(l, r))
	seg.update(l, mx)
dp = [0] * (N + 1)
dp[0] = 1
for i in range(N):
	dp[i + 1] += dp[i]
	dp[i + 1] %= mod
	dp[seg.query(i, i + 1) + 1] += dp[i]
	dp[i + 1] %= mod
print(dp[-1])


from sys import setrecursionlimit
setrecursionlimit(10000000)
n = int(input())
xds = [tuple(map(int, input().split())) for _ in range(n)]
xds.sort()
xds.insert(0, (-1000000001, 2000000004))
n += 1

def make_blocks(i):
	(x, d) = xds[i]
	right = x + d
	res = []
	nexti = i + 1
	while nexti < n:
		(xn, dn) = xds[nexti]
		if xn < right:
			(l, lasti) = make_blocks(nexti)
			res.append(l)
			nexti = lasti + 1
		else:
			return (res, nexti - 1)
	return (res, n - 1)
(l, _) = make_blocks(0)

def count(l):
	ans = 1
	for ll in l:
		ans = ans * (1 + count(ll)) % 998244353
	return ans
print(count(l))


n = int(input())
a = sorted((tuple(map(int, input().split())) for i in range(n)))
a.append((10 ** 18, 1))
mo = 998244353
dp = [0] * (n + 1)
dp[n] = 1
f = list(range(n))
fr = list(range(n))
bd = [x + d for (x, d) in a]

def getF(u):
	if f[f[u]] != f[u]:
		f[u] = getF(f[u])
		return f[u]
	return f[u]

def uniF(u, v):
	u = getF(u)
	v = getF(v)
	if u == v:
		return
	f[u] = v
	fr[v] = max(fr[v], fr[u])
	bd[v] = max(bd[v], bd[u])
for i in range(n - 1, -1, -1):
	cur = i
	while fr[getF(cur)] + 1 < n and a[fr[getF(cur)] + 1][0] < bd[getF(cur)]:
		uniF(cur, fr[getF(cur)] + 1)
	dp[i] = (dp[i + 1] + dp[fr[getF(cur)] + 1]) % mo
print(dp[0])


import sys
from bisect import bisect_left
from operator import itemgetter

class SegTreeMax:

	def __init__(self, n, 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 += 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):
		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) = 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])


import sys
INF = 1 << 60
MOD = 998244353
sys.setrecursionlimit(2147483647)
input = lambda : sys.stdin.buffer.readline().rstrip()
from bisect import bisect_left

class LazySegmentTree(object):

	def __init__(self, A, dot, unit, compose, identity, act):
		logn = (len(A) - 1).bit_length()
		n = 1 << logn
		tree = [unit] * (2 * n)
		for (i, v) in enumerate(A):
			tree[i + n] = v
		for i in range(n - 1, 0, -1):
			tree[i] = dot(tree[i << 1], tree[i << 1 | 1])
		(self._n, self._logn, self._tree, self._lazy) = (n, logn, tree, [identity] * (2 * n))
		(self._dot, self._unit, self._compose, self._identity, self._act) = (dot, unit, compose, identity, act)

	def _ascend(self, i):
		(tree, lazy, dot, act) = (self._tree, self._lazy, self._dot, self._act)
		while i > 1:
			i >>= 1
			tree[i] = act(lazy[i], dot(tree[i << 1], tree[i << 1 | 1]))

	def _descend(self, i):
		(tree, lazy, identity, compose, act) = (self._tree, self._lazy, self._identity, self._compose, self._act)
		for k in range(self._logn, 0, -1):
			p = i >> k
			f = lazy[p]
			(tree[p << 1], lazy[p << 1]) = (act(f, tree[p << 1]), compose(f, lazy[p << 1]))
			(tree[p << 1 | 1], lazy[p << 1 | 1]) = (act(f, tree[p << 1 | 1]), compose(f, lazy[p << 1 | 1]))
			lazy[p] = identity

	def range_act(self, l, r, f):
		l += self._n
		r += self._n
		(l0, r0) = (l, r)
		(tree, lazy, act, compose) = (self._tree, self._lazy, self._act, self._compose)
		while l < r:
			if l & 1:
				(tree[l], lazy[l]) = (act(f, tree[l]), compose(f, lazy[l]))
				l += 1
			if r & 1:
				r -= 1
				(tree[r], lazy[r]) = (act(f, tree[r]), compose(f, lazy[r]))
			l >>= 1
			r >>= 1
		self._ascend(l0)
		self._ascend(r0 - 1)

	def sum(self, l, r):
		l += self._n
		r += self._n
		l_val = r_val = self._unit
		(tree, dot) = (self._tree, self._dot)
		while l < r:
			if l & 1:
				l_val = dot(l_val, tree[l])
				l += 1
			if r & 1:
				r -= 1
				r_val = dot(tree[r], r_val)
			l >>= 1
			r >>= 1
		return dot(l_val, r_val)
from operator import add

def resolve():
	n = int(input())
	XD = [tuple(map(int, input().split())) for _ in range(n)]
	XD.sort()
	X = [a[0] for a in XD]
	A = [0] * n
	A[-1] = 1

	def compose(f, g):
		return f if f != INF else g

	def act(f, x):
		return f if f != INF else x
	tree = LazySegmentTree(A, add, 0, compose, INF, act)
	for i in range(n - 2, -1, -1):
		x = tree.sum(i + 1, n)
		tree.range_act(i, i + 1, (x + 1) % MOD)
		(x, d) = XD[i]
		j = bisect_left(X, x + d)
		tree.range_act(i + 1, j, 0)
	print((tree.sum(0, n) + 1) % MOD)
resolve()


import sys
input = sys.stdin.readline
import bisect
from operator import itemgetter
N = int(input())
R = [tuple(map(int, input().split())) for i in range(N)] + [(1 << 31, 1 << 31)]
R.sort(key=itemgetter(0))
RMAX = [x + y for (x, y) in R]
seg_el = 1 << N.bit_length()
SEG = [-1] * (2 * seg_el)

def update(n, x, seg_el):
	i = n + seg_el
	SEG[i] = x
	i >>= 1
	while i != 0:
		SEG[i] = max(SEG[i * 2], SEG[i * 2 + 1])
		i >>= 1

def getvalues(l, r):
	L = l + seg_el
	R = r + seg_el
	ANS = -1 << 30
	while L < R:
		if L & 1:
			ANS = max(ANS, SEG[L])
			L += 1
		if R & 1:
			R -= 1
			ANS = max(ANS, SEG[R])
		L >>= 1
		R >>= 1
	return ANS
for i in range(N - 1, -1, -1):
	x = bisect.bisect_left(R, (RMAX[i], 0))
	MAX = getvalues(i, x)
	if MAX == -1:
		update(i, x, seg_el)
	else:
		update(i, MAX, seg_el)
mod = 998244353
DP = [0] * (N + 1)
DP[0] = 1
for i in range(N):
	DP[i + 1] = (DP[i] + DP[i + 1]) % mod
	DP[getvalues(i, i + 1)] = (DP[i] + DP[getvalues(i, i + 1)]) % mod
print(DP[-1] % mod)


mod = 998244353
(N, *XD) = map(int, open(0).read().split())
XD = sorted(zip(*[iter(XD)] * 2), reverse=True)
S = [(10000000000.0, 0)]
dp = [1] + [0] * N
for (i, (x, d)) in enumerate(XD):
	j = i
	while S[-1][0] < x + d:
		(_, j) = S.pop()
	S.append((x, j))
	dp[i + 1] = (dp[i] + dp[j]) % mod
print(dp[-1])


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)


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):
		self.indivisual[i] = v
		self.array[i // self.size] = max(self.array[i // self.size], v)

	def search(self, 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
solve()


def main():
	mod = 998244353
	n = int(input())
	ab = sorted([tuple(map(int, input().split())) for _ in [0] * n])
	next_idx = [-1] * n
	for i in range(n - 1, -1, -1):
		dist = sum(ab[i])
		now = i
		while now < n - 1:
			(a1, b1) = ab[now + 1]
			if a1 < dist:
				now = next_idx[now + 1]
			else:
				break
		next_idx[i] = now
	dp = [0] * (n + 1)
	dp[n] = 1
	for i in range(n - 1, -1, -1):
		dp[i] = (dp[i + 1] + dp[next_idx[i] + 1]) % mod
	print(dp[0])
main()


from collections import deque
n = int(input())
info = [list(map(int, input().split())) for i in range(n)]
MOD = 998244353
info = [(10 ** 10, 10 ** 10)] + sorted(info, reverse=True)
dp = [0] * (n + 1)
dp[0] = 1
q = deque([])
for i in range(n):
	if sum(info[i + 1]) <= info[i][0]:
		dp[i + 1] = 2 * dp[i]
		dp[i + 1] %= MOD
		q.append((i, info[i]))
	elif sum(info[i + 1]) <= q[-1][1][0]:
		dp[i + 1] = dp[i] + dp[q[-1][0]]
		dp[i + 1] %= MOD
	else:
		while q:
			q.pop()
			if sum(info[i + 1]) <= q[-1][1][0]:
				dp[i + 1] = dp[i] + dp[q[-1][0]]
				dp[i + 1] %= MOD
				break
print(dp[-1] % MOD)


MOD = 998244353
import bisect
N = int(input())
xdlist = []
for _ in range(N):
	(x, d) = map(int, input().split())
	xdlist.append((x, d - 0.5))
xdlist.sort()

class SegTree:

	def __init__(self, init_val, segfunc, ide_ele):
		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 += 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):
		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

def segfunc(x, y):
	return max(x, y)
ide_ele = -float('inf')
seg = SegTree([-float('inf')] * N, segfunc, ide_ele)
for i in reversed(range(N)):
	(x, d) = xdlist[i]
	right = x + d
	pos = bisect.bisect(xdlist, (x + d, float('inf')))
	if pos == i + 1:
		seg.update(i, i)
	else:
		max_pos = seg.query(i + 1, pos)
		seg.update(i, max_pos)
dp = [2] * N
for i in reversed(range(N - 1)):
	dp[i] = dp[i + 1]
	right = seg.query(i, i + 1)
	if right < N - 1:
		dp[i] += dp[right + 1]
	else:
		dp[i] += 1
	dp[i] %= MOD
print(dp[0])


import sys, bisect
input = sys.stdin.readline
n = int(input())
dg = 10 ** 10
mod = 998244353
xd = []
for i in range(n):
	(x, d) = map(int, input().split())
	xd.append((x + 10 ** 9) * dg + d)
xd.sort()
dp = [0] * (n + 1)
ma = list(range(n + 1))

def init_max(init_max_val):
	for i in range(n):
		seg_max[i + num_max - 1] = init_max_val[i]
	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
ide_ele_max = -1
num_max = 2 ** (n - 1).bit_length()
seg_max = [ide_ele_max] * 2 * num_max
init_max(ma)
dp[n] = 1
for i in range(n - 1, -1, -1):
	(x, d) = (xd[i] // dg, xd[i] % dg)
	k = bisect.bisect_left(xd, (x + d) * dg)
	ma[i] = query_max(i, k)
	update_max(i, ma[i])
	dp[i] = (dp[i + 1] + dp[ma[i] + 1]) % mod
print(dp[0] % mod)


import sys, math, itertools, collections, bisect
input = lambda : sys.stdin.buffer.readline().rstrip().decode('utf-8')
inf = float('inf')
mod = 998244353
mans = 998244353
ans = 0
count = 0
pro = 1
sys.setrecursionlimit(10 ** 6)
n = int(input())
XD = [tuple(map(int, input().split())) for i in range(n)]
XD.append((-10 ** 10, inf))
XD.sort()
now = 0
visited1 = []

def dfs(node):
	visited1.append(node)
	global now
	pro = 1
	while now < n:
		if XD[now + 1][0] < XD[node][0] + XD[node][1]:
			now += 1
			pro *= dfs(now)
			pro %= mod
		else:
			break
	return pro + 1
ans = dfs(0)
print((ans - 1) % mod)


def i1():
	return int(input())

def i2():
	return [int(i) for i in input().split()]
import bisect
mod = 998244353
n = int(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])


import sys
from bisect import bisect_left
MOD = 998244353
import math

class SegmentTree(object):

	def __init__(self, N):
		self.idelem = -10 ** 9
		self.func = max
		self.N0 = 1
		while self.N0 < N:
			self.N0 <<= 1
		self.tree = [self.idelem] * (2 * self.N0)

	def update(self, k, x):
		k += self.N0 - 1
		self.tree[k] = x
		while k > 1:
			k = (k - 1) // 2
			self.tree[k] = self.func(self.tree[2 * k + 1], self.tree[2 * k + 2])

	def query(self, l, r):
		l += self.N0 - 1
		r += self.N0 - 1
		s = self.idelem
		while l < r:
			if r % 2 == 0:
				r -= 1
				s = self.func(s, self.tree[r])
			if l % 2 == 0:
				s = self.func(s, self.tree[l])
				l += 1
			l //= 2
			r //= 2
		return s

def solve(N: int, X: 'List[int]', D: 'List[int]'):
	reachable = [0] * N
	(X, D) = zip(*sorted(zip(X, D)))
	for (i, (x, d)) in enumerate(zip(X, D)):
		reachable[i] = bisect_left(X, x + d)
	seg = SegmentTree(N)
	for v in reversed(range(N)):
		if v == N - 1:
			seg.update(v, reachable[v])
			continue
		a = seg.query(v, reachable[v])
		if a > 0:
			seg.update(v, a)
		else:
			seg.update(v, v + 1)
	true_reachable = [seg.query(v, v + 1) for v in range(N)]
	dp = [0] * (N + 1)
	dp[N] = 1
	for v in reversed(range(N)):
		dp[v] = dp[v + 1] + dp[true_reachable[v]]
		dp[v] %= MOD
	print(dp[0])
	return

def main():

	def iterate_tokens():
		for line in sys.stdin:
			for word in line.split():
				yield word
	tokens = iterate_tokens()
	N = int(next(tokens))
	X = [int()] * N
	D = [int()] * N
	for i in range(N):
		X[i] = int(next(tokens))
		D[i] = int(next(tokens))
	solve(N, X, D)
main()


mod = 998244353
n = 0
x = []
d = []

def search(s):
	lo = 0
	hi = n - 1
	while lo <= hi:
		mid = (lo + hi) // 2
		if s > x[mid]:
			lo = mid + 1
		elif s < x[mid]:
			hi = mid - 1
		else:
			return mid
	return max(lo, hi)

def __starting_point():
	xd = []
	n = int(input())
	for i in range(n):
		(xi, di) = map(int, input().split())
		xd.append((xi, di))
	xd.sort()
	x = list(map(lambda x: x[0], xd))
	d = list(map(lambda x: x[1], xd))
	dp = [0] * (n + 1)
	dp[-1] = 1
	next = [0] * n
	st = []
	st.append((n, 2000000000.0))
	for i in range(n - 1, -1, -1):
		while st[-1][1] < x[i] + d[i]:
			st.pop()
		next[i] = st[-1][0]
		st.append((i, x[i]))
	for i in range(n - 1, -1, -1):
		dp[i] = (dp[next[i]] + dp[i + 1]) % mod
	print(dp[0])
__starting_point()


from bisect import bisect_left
LARGE = 998244353

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):
		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

def solve(n, x_list, d_list):
	reach_right = [0] * n
	reach_right[-1] = n - 1
	seg = SegmentTree(list(range(n)), max, -1)
	for i in range(n - 2, -1, -1):
		j = bisect_left(x_list, x_list[i] + d_list[i])
		k = seg.query(i, j)
		seg.update(i, k)
		reach_right[i] = k
	dp = [[0] * 2 for _ in range(n)]
	dp[n - 1][0] = 1
	dp[n - 1][1] = 1
	for i in range(n - 2, -1, -1):
		dp[i][0] = (dp[i + 1][0] + dp[i + 1][1]) % LARGE
		j = reach_right[i] + 1
		if j <= n - 1:
			dp[i][1] = (dp[j][0] + dp[j][1]) % LARGE
		else:
			dp[i][1] = 1
	return (dp[0][0] + dp[0][1]) % LARGE

def main():
	n = int(input())
	xd_list = sorted([list(map(int, input().split())) for _ in range(n)], key=lambda x: x[0])
	x_list = [xd[0] for xd in xd_list]
	d_list = [xd[1] for xd in xd_list]
	res = solve(n, x_list, d_list)
	print(res)

def test():
	assert solve(2, [1, 3], [5, 3]) == 3
	assert solve(3, [-1, 3, 6], [10, 3, 5]) == 5
	assert solve(4, [-10, -4, 4, 7], [3, 3, 3, 10]) == 16
test()
main()


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()


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)
main()


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])


N = int(input())
XD = []
for _ in range(N):
	(x, d) = map(int, input().split())
	XD.append((x, x + d))
MOD = 998244353
XD.sort(reverse=True)
sei = [(10 ** 9, 0)]
pattern = [0] * (N + 1)
pattern[0] = 1
for (i, (s, e)) in enumerate(XD):
	ei = i
	while e > sei[-1][0]:
		(_, ei) = sei.pop()
	sei.append((s, ei))
	pattern[i + 1] = (pattern[i] + pattern[ei]) % MOD
print(pattern[-1])


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])


MOD = 998244353
import bisect
import sys
input = sys.stdin.buffer.readline
N = int(input())
XR = []
for i in range(N):
	(X, D) = map(int, input().split())
	XR.append((X, X + D))
XR.sort()
(X, R) = map(list, zip(*XR))
inds = [bisect.bisect_left(X, r) - 1 for r in R]
l = 2 ** (N - 1).bit_length()
data = [0] * l + inds + [0] * (l - N)
for i in range(l - 1, 0, -1):
	data[i] = max(data[2 * i], data[2 * i + 1])

def set(i, val):
	i += l
	data[i] = val
	i //= 2
	while i > 0:
		data[i] = max(data[2 * i], data[2 * i + 1])
		i //= 2

def get(i, j):
	i += l
	j += l
	s = data[i]
	while j - i > 0:
		if i & 1:
			s = max(s, data[i])
			i += 1
		if j & 1:
			s = max(s, data[j - 1])
			j -= 1
		i //= 2
		j //= 2
	return s
for i in range(N - 1, -1, -1):
	set(i, get(i, inds[i] + 1))
dp = [0] * (N + 1)
dp[N] = 1
for i in range(N - 1, -1, -1):
	dp[i] = (dp[i + 1] + dp[data[l + i] + 1]) % MOD
print(dp[0])


import sys
import bisect
from collections import deque
sys.setrecursionlimit(10 ** 7)
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
readlines = sys.stdin.buffer.readlines
N = int(readline())
MOD = 998244353
XD = [[int(x) for x in readline().split()] for _ in range(N)]
XD.sort()
NXT = deque()
E = [[] for _ in range(N)]
for i in range(N - 1, -1, -1):
	(x, d) = XD[i]
	while NXT:
		(j, nx) = NXT.pop()
		if nx < x + d:
			E[i].append(j)
		else:
			NXT.append((j, nx))
			break
	NXT.append((i, x))

def dfs(i):
	rtn = 1
	for v in E[i]:
		rtn *= dfs(v)
		rtn %= MOD
	return rtn + 1
ans = 1
for (i, x) in NXT:
	ans *= dfs(i)
	ans %= MOD
print(ans % MOD)


import sys
reader = (s.rstrip() for s in sys.stdin)
input = reader.__next__

class RangeMinimumQuery:

	def __init__(self, n, F=min, e=float('inf'), fill=None):
		self.n0 = 2 ** (n - 1).bit_length()
		self.F = F
		self.e = e
		if fill is None:
			fill = e
		self.data = [fill] * (2 * self.n0)

	def construct(self, a):
		for (i, x) in enumerate(a):
			self.data[i + self.n0 - 1] = x
		for i in range(self.n0 - 2, -1, -1):
			self.data[i] = self.F(self.data[2 * i + 1], self.data[2 * i + 2])

	def query(self, l, r):
		l += self.n0
		r += self.n0
		res = self.e
		while l < r:
			if r & 1:
				r -= 1
				res = self.F(res, self.data[r - 1])
			if l & 1:
				res = self.F(res, self.data[l - 1])
				l += 1
			l >>= 1
			r >>= 1
		return res

	def update(self, i, x):
		i += self.n0 - 1
		self.data[i] = x
		while i:
			i = ~-i // 2
			self.data[i] = self.F(self.data[2 * i + 1], self.data[2 * i + 2])
from bisect import bisect_left
mod = 998244353
n = int(input())
xd = [list(map(int, input().split())) for i in range(n)]
xd.sort()
xs = [i for (i, j) in xd]
RMQ = RangeMinimumQuery(n, max, 0, 0)
RMQ.construct(list(range(n)))
for i in reversed(range(n)):
	r = sum(xd[i])
	j = bisect_left(xs, r)
	k = RMQ.query(i, j)
	RMQ.update(i, k)
DP = [0] * (n + 1)
DP[-1] = 1
for i in reversed(range(n)):
	j = RMQ.query(i, i + 1)
	DP[i] = DP[i + 1] + DP[j + 1]
	DP[i] %= mod
print(DP[0])


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()
	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':
			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):
				tree[idx + self._size - 1] = val
			for idx in range(self._size - 2, -1, -1):
				tree[idx] = self._seg_func(tree[2 * idx + 1], tree[2 * idx + 2])
			return tree

		def update(self, index: int, value: int) -> None:
			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]':
			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]))
		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)
main()


import sys
sys.setrecursionlimit(10 ** 9)
mod = 998244353

def init_max(init_max_val, n):
	for i in range(n):
		seg_max[i + num_max - 1] = init_max_val[i]
	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
ide_ele_max = -1
num_max = 1 << 18
seg_max = [ide_ele_max] * 2 * num_max
N = int(input())
tmpX = []
for i in range(N):
	(x, d) = list(map(int, input().split()))
	tmpX.append((x, d))
tmpX.sort()
(X, D) = ([0] * N, [0] * N)
for i in range(N):
	X[i] = tmpX[i][0]
	D[i] = tmpX[i][1]
to = [0] * N
for i in range(N):
	to[i] = i
init_max(to, N)
for i in range(N - 1, -1, -1):
	ok = i
	ng = N
	while ng - ok > 1:
		mid = (ng + ok) // 2
		if X[i] + D[i] > X[mid]:
			ok = mid
		else:
			ng = mid
	to[i] = query_max(i, ok + 1)
	update_max(i, to[i])
dp = [0] * (N + 1)
dp[0] = 1
for i in range(N):
	dp[i + 1] += dp[i]
	dp[i + 1] %= mod
	dp[to[i] + 1] += dp[i]
	dp[to[i] + 1] %= mod
print(dp[N])


n = int(input())
x = [list(map(int, input().split())) for i in range(n)]
x.sort(key=lambda x: x[0])
x.append([2 * 10 ** 9 + 1, 0])
y = [0] * (n - 1) + [n - 1]
a = [0] * (n - 1) + [2]
for i in range(n - 2, -1, -1):
	j = i + 1
	while x[j][0] < sum(x[i]):
		j = y[j] + 1
	y[i] = j - 1
for i in range(n - 2, -1, -1):
	a[i] = a[y[i] + 1] if y[i] + 1 < n else 1
	a[i] = (a[i] + a[i + 1]) % 998244353
print(a[0])


mod = 998244353
N = int(input())
X = []
for _ in range(N):
	(x, d) = map(int, input().split())
	X.append((x, x + d))
X = sorted(X, key=lambda x: x[0])
L = [(0, -(10 ** 9 + 1), 10 ** 9 + 1)]
P = [-1] * (N + 1)
for (i, (x, y)) in enumerate(X):
	while L[-1][2] <= y:
		if L[-1][2] > x and P[i + 1] < 0:
			P[i + 1] = L[-1][0]
		L.pop()
	if P[i + 1] < 0:
		P[i + 1] = L[-1][0]
	L.append((i + 1, x, y))
C = [[] for _ in range(N + 1)]
for (i, p) in enumerate(P):
	if p >= 0:
		C[p].append(i)
Y = [1] * (N + 1)
for i in range(N + 1)[::-1]:
	s = 1
	for j in C[i]:
		s = s * (Y[j] + 1) % mod
	Y[i] = s
print(Y[0])


INF = 10 ** 18
MOD = 998244353
N = int(input())
robots = [(-INF, INF)]
for _ in range(N):
	(x, d) = map(int, input().split())
	robots.append((x, x + d))
robots.sort()
stack = list()
tree = [[] for _ in range(N + 1)]
for i in range(N + 1)[::-1]:
	(x, r) = robots[i]
	while stack and stack[-1][0] < r:
		(y, j) = stack.pop()
		tree[i].append(j)
	stack.append((x, i))
stack = list()
stack.append(0)
visited = [0 for _ in range(N + 1)]
visited[0] = 1
order = [None for _ in range(N + 1)]
order[0] = 0
od = 0
while stack:
	node = stack.pop()
	for adj in tree[node]:
		if not visited[adj]:
			visited[adj] = 1
			od += 1
			order[od] = adj
			stack.append(adj)
dp = [1 for _ in range(N + 1)]
for node in order[::-1]:
	for adj in tree[node]:
		dp[node] *= dp[adj]
	dp[node] += 1
	dp[node] %= MOD
print(dp[0] - 1)


from collections import defaultdict, deque
from heapq import heappush, heappop
from bisect import bisect_left, bisect_right
import sys, random, itertools, math
sys.setrecursionlimit(10 ** 5)
input = sys.stdin.readline
sqrt = math.sqrt

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

def LF():
	return list(map(float, input().split()))

def LI_():
	return list(map(lambda x: int(x) - 1, input().split()))

def II():
	return int(input())

def IF():
	return float(input())

def LS():
	return list(map(list, input().split()))

def S():
	return list(input().rstrip())

def IR(n):
	return [II() for _ in range(n)]

def LIR(n):
	return [LI() for _ in range(n)]

def FR(n):
	return [IF() for _ in range(n)]

def LFR(n):
	return [LI() for _ in range(n)]

def LIR_(n):
	return [LI_() for _ in range(n)]

def SR(n):
	return [S() for _ in range(n)]

def LSR(n):
	return [LS() for _ in range(n)]
mod = 998244353
inf = 10000000000.0

def solve():

	def init_max(init_max_val):
		for i in range(n):
			seg_max[i + num_max - 1] = init_max_val[i]
		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 = II()
	ide_ele_max = -1
	num_max = 2 ** n.bit_length()
	seg_max = [ide_ele_max] * 2 * num_max
	xd = LIR(n)
	xd.sort()
	x = [x for (x, d) in xd]
	dp = [[0] * 2 for i in range(n + 1)]
	On = 0
	Off = 1
	dp[-1][On] = 1
	for i in range(n - 1, -1, -1):
		dp[i][Off] = (dp[i + 1][On] + dp[i + 1][Off]) % mod
		j = bisect_right(x, x[i] + xd[i][1] - 1) - 1
		if j == i:
			dp[i][On] = (dp[i + 1][On] + dp[i + 1][Off]) % mod
			update_max(i, i)
		else:
			j = query_max(i, j + 1)
			dp[i][On] = dp[j][On]
			update_max(i, j)
	print(sum(dp[0]) % mod)
	return
solve()


import heapq
mod = 998244353
n = int(input())
robot = [tuple(map(int, input().split())) for _ in range(n)]
robot.sort(reverse=True)
parent = list(range(n))
root = []
for i in range(n):
	(x, d) = robot[i]
	while root:
		r = heapq.heappop(root)
		if r[0] < x + d:
			parent[r[1]] = i
		else:
			heapq.heappush(root, r)
			break
	heapq.heappush(root, (x, i))
count = 1
dp = [1] * n
for i in range(n):
	p = parent[i]
	if p == i:
		count = count * (dp[i] + 1) % mod
	else:
		dp[p] = dp[p] * (dp[i] + 1) % mod
print(count)


n = int(input())
arr = [list(map(int, input().split())) for _ in range(n)]
mod = 998244353
ans = 0
arr.sort(key=lambda x: x[0], reverse=True)
pos = [i[0] for i in arr]
moved = [sum(i) for i in arr]
children = [i for i in range(-1, n)]
for i in range(1, n):
	parent = moved[i]
	child = children[i]
	cmp = pos[child]
	while cmp < parent:
		child = children[child]
		if child == -1:
			break
		cmp = pos[child]
	children[i] = child
dp = [0] * (n + 1)
dp[n] = 1
for i in range(n):
	dp[i] = dp[i - 1] + dp[children[i]]
	dp[i] %= mod
print(dp[n - 1])


import sys
input = sys.stdin.readline
N = int(input())
XD = [tuple(map(int, input().split())) for i in range(N)]
XD.sort()
MOD = 998244353
ns = [-1] * N
for (i, (x, d)) in reversed(list(enumerate(XD))):
	tmp = i
	while tmp < N - 1:
		(nx, _) = XD[tmp + 1]
		if nx < x + d:
			tmp = ns[tmp + 1]
		else:
			break
	ns[i] = tmp
dp = [0] * (N + 1)
dp[N] = 1
for i in range(N - 1, -1, -1):
	dp[i] = (dp[i + 1] + dp[ns[i] + 1]) % MOD
print(dp[0])


def main():
	mod = 998244353
	n = int(input())
	ab = [tuple(map(int, input().split())) for _ in [0] * n]
	ab.sort()
	next_a = [-1] * n
	dp = [0] * (n + 1)
	dp[n] = 1
	for i in range(n - 1, -1, -1):
		(a0, b0) = ab[i]
		dist = a0 + b0
		now = i
		while now < n - 1:
			(a1, b1) = ab[now + 1]
			if a1 < dist:
				now = next_a[now + 1]
			else:
				break
		next_a[i] = now
	for i in range(n - 1, -1, -1):
		dp[i] = (dp[i + 1] + dp[next_a[i] + 1]) % mod
	print(dp[0] % mod)
main()


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
			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)
	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()


import sys

def input():
	return sys.stdin.readline()
n = int(input())
xd = [[int(i) for i in input().split()] for _ in range(n)]
xd.sort()
num_max = 2 ** (n - 1).bit_length()
seg_max = [0] * (2 * num_max)
ide_ele_max = -1

def init_max(init_max_val):
	for i in range(n):
		seg_max[i + num_max - 1] = init_max_val[i]
	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
y = [0] * n
j = n - 1
for (x, d) in reversed(xd):
	if x + d > xd[-1][0]:
		y[j] = n
	else:
		mi = 0
		ma = n - 1
		while mi != ma:
			m = (mi + ma) // 2 + 1
			if xd[m][0] < x + d:
				mi = m
			else:
				ma = m - 1
		if mi == j:
			y[j] = mi + 1
		else:
			y[j] = query_max(j + 1, mi + 1)
	update_max(j, y[j])
	j -= 1
dp = [0] * (n + 1)
dp[-1] = 1
j = n - 1
for i in y:
	if j == y[j]:
		dp[j] = dp[j + 1]
	dp[j] = (dp[j + 1] + dp[y[j]]) % 998244353
	j -= 1
print(dp[0])


import sys
from bisect import bisect_left, bisect_right
input = sys.stdin.readline
ide = 0

def func(a, b):
	return max(a, b)

class SegmentTree:

	def __init__(self, ls, commutative=True):
		if commutative == True:
			self.n = len(ls)
			self.tree = [ide for i in range(self.n)] + ls
		else:
			self.n = 2 ** (len(ls) - 1).bit_length()
			self.tree = [ide for i in range(self.n)] + ls + [ide for i in range(self.n - len(ls))]
		for i in range(1, self.n)[::-1]:
			self.tree[i] = func(self.tree[i << 1 | 0], self.tree[i << 1 | 1])

	def getall(self):
		return self.tree[1]

	def get(self, l, r):
		lret = ide
		rret = ide
		l += self.n
		r += self.n
		while l < r:
			if l & 1:
				lret = func(lret, self.tree[l])
				l += 1
			if r & 1:
				rret = func(self.tree[r - 1], rret)
			l >>= 1
			r >>= 1
		ret = func(lret, rret)
		return ret

	def update(self, i, x):
		i += self.n
		self.tree[i] = x
		while i > 1:
			i >>= 1
			self.tree[i] = func(self.tree[i << 1 | 0], self.tree[i << 1 | 1])
n = int(input())
xd = [list(map(int, input().split())) for i in range(n)]
mod = 998244353
xd.sort()
xls = list(zip(*xd))[0]
rls = [0] * n
st = SegmentTree(rls)
for i in range(n)[::-1]:
	idx = bisect_left(xls, xd[i][0] + xd[i][1]) - 1
	x = st.get(i, idx + 1)
	st.update(i, max(i, x))
dp = [0] * n
dp[-1] = 2
for i in range(n - 1)[::-1]:
	x = st.get(i, i + 1)
	if x == n - 1:
		dp[i] = dp[i + 1] + 1
	else:
		dp[i] = dp[i + 1] + dp[x + 1]
	dp[i] %= mod
print(dp[0])


import sys
from bisect import bisect_left

def input():
	return sys.stdin.readline().strip()

def list2d(a, b, c):
	return [[c] * b for i in range(a)]

def list3d(a, b, c, d):
	return [[[d] * c for j in range(b)] for i in range(a)]

def list4d(a, b, c, d, e):
	return [[[[e] * d for j in range(c)] for j in range(b)] for i in range(a)]

def ceil(x, y=1):
	return int(-(-x // y))

def INT():
	return int(input())

def MAP():
	return map(int, input().split())

def LIST(N=None):
	return list(MAP()) if N is None else [INT() for i in range(N)]

def Yes():
	print('Yes')

def No():
	print('No')

def YES():
	print('YES')

def NO():
	print('NO')
sys.setrecursionlimit(10 ** 9)
INF = 10 ** 18
MOD = 998244353

class SegTree:

	def __init__(self, n, func, intv, A=[]):
		self.n = n
		self.func = func
		self.intv = intv
		n2 = 1
		while n2 < n:
			n2 <<= 1
		self.n2 = n2
		self.tree = [self.intv] * (n2 << 1)
		if A:
			for i in range(n):
				self.tree[n2 + i] = A[i]
			for i in range(n2 - 1, -1, -1):
				self.tree[i] = self.func(self.tree[i * 2], self.tree[i * 2 + 1])

	def update(self, i, x):
		i += self.n2
		self.tree[i] = x
		while i > 0:
			i >>= 1
			self.tree[i] = self.func(self.tree[i * 2], self.tree[i * 2 + 1])

	def query(self, a, b):
		l = a + self.n2
		r = b + self.n2
		s = self.intv
		while l < r:
			if r & 1:
				r -= 1
				s = self.func(s, self.tree[r])
			if l & 1:
				s = self.func(s, self.tree[l])
				l += 1
			l >>= 1
			r >>= 1
		return s

	def get(self, i):
		return self.tree[i + self.n2]

	def all(self):
		return self.tree[1]

	def print(self):
		for i in range(self.n):
			print(self.get(i), end=' ')
		print()
N = INT()
XD = []
for _ in range(N):
	(x, d) = MAP()
	XD.append((x, d))
XD.sort()
(X, _) = zip(*XD)
X = list(X)
X += [INF]
st = SegTree(N + 1, max, -INF)
st.update(N, N)
for i in range(N - 1, -1, -1):
	(x, d) = XD[i]
	j = bisect_left(X, x + d)
	mx = st.query(i, j)
	st.update(i, max(i, mx))
dp = [0] * (N + 1)
dp[N] = 1
for i in range(N - 1, -1, -1):
	dp[i] += dp[i + 1]
	dp[i] += dp[st.get(i) + 1]
	dp[i] %= MOD
ans = dp[0]
print(ans)


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])
main()


import bisect
import sys
input = sys.stdin.readline

class SegmentTreeRMQ(object):

	def __init__(self, size, value):
		self.len = 1 << size.bit_length()
		self.array = [value] * (2 * self.len)

	def update(self, i, x):
		i += self.len
		while i > 0:
			self.array[i] = max(self.array[i], x)
			i >>= 1

	def get(self, i):
		return self.array[i + self.len]

	def get_maximum(self, l, r):
		L = l + self.len
		R = r + self.len
		ANS = -1 << 30
		while L < R:
			if L & 1:
				ANS = max(ANS, self.array[L])
				L += 1
			if R & 1:
				R -= 1
				ANS = max(ANS, self.array[R])
			L >>= 1
			R >>= 1
		return ANS
N = int(input())
xd_array = [list(map(int, input().split())) for _ in range(N)]
xd_array = sorted(xd_array, key=lambda x: x[0])
x_array = [i[0] for i in xd_array]
d_array = [i[1] for i in xd_array]
mod = 998244353
tree = SegmentTreeRMQ(N, -1)
ans_array = [0] * (N + 1)
ans_array[-1] = 1
for i in range(N - 1, -1, -1):
	move = x_array[i] + d_array[i] - 0.1
	max_index = bisect.bisect_left(x_array, move)
	max_move = max(i, tree.get_maximum(i, max_index))
	tree.update(i, max_move)
	ans_array[i] = (ans_array[i + 1] + ans_array[max_move + 1]) % mod
print(ans_array[0])


from bisect import bisect_left

class SegTree:

	def __init__(self, raw_data):
		n = len(raw_data)
		self.size = 1 << n.bit_length()
		self.data = [0] * (2 * self.size)
		self.build(raw_data)

	def build(self, raw_data):
		for (i, x) in enumerate(raw_data):
			self.data[self.size + i] = x
		for i in range(self.size - 1, 0, -1):
			x = self.data[2 * i]
			y = self.data[2 * i + 1]
			self.data[i] = x if x > y else y

	def update(self, i, x):
		i += self.size
		self.data[i] = x
		i >>= 1
		while i:
			x = self.data[2 * i]
			y = self.data[2 * i + 1]
			self.data[i] = x if x > y else y
			i >>= 1

	def get_data(self, i):
		return self.data[i + self.size]

	def get_max(self, L, R):
		L += self.size
		R += self.size + 1
		x = 0
		while L < R:
			if L & 1:
				y = self.data[L]
				if x < y:
					x = y
				L += 1
			if R & 1:
				R -= 1
				y = self.data[R]
				if x < y:
					x = y
			L >>= 1
			R >>= 1
		return x
N = int(input())
robots = sorted([tuple(map(int, input().split())) for _ in range(N)])
(X, D) = zip(*robots)
mod = 998244353
affects = [0] + [bisect_left(X, x + d) for (x, d) in robots]
seg = SegTree(affects)
S = [0] * len(affects)
for n in range(N, 0, -1):
	affect = affects[n]
	x = seg.get_max(n, affect)
	S[n] = x
	seg.update(n, x)
dp = [0] * (N + 1)
dp[0] = 1
dp_cum = [1] * (N + 1)
for (n, r) in enumerate(S[1:], 1):
	dp[r] += dp_cum[n - 1]
	dp[r] %= mod
	dp_cum[n] = dp_cum[n - 1] + dp[n]
	dp_cum[n] %= mod
print(dp_cum[-1])


def main():
	import sys
	from bisect import bisect_left
	input = sys.stdin.readline

	class SegTree:

		def __init__(self, N):
			self.N0 = 2 ** (N - 1).bit_length()
			self.INF = 2100000000
			self.seg_min = [-self.INF] * (2 * self.N0)

		def update(self, index, value):
			index += self.N0 - 1
			self.seg_min[index] = value
			while index > 0:
				index = index - 1 >> 1
				L = self.seg_min[index * 2 + 1]
				R = self.seg_min[index * 2 + 2]
				if L > R:
					self.seg_min[index] = L
				else:
					self.seg_min[index] = R

		def query(self, first, last):
			first += self.N0 - 1
			last += self.N0 - 1
			ret = -self.INF
			while first <= last:
				if not first & 1:
					ret_new = self.seg_min[first]
					if ret_new > ret:
						ret = ret_new
				if last & 1:
					ret_new = self.seg_min[last]
					if ret_new > ret:
						ret = ret_new
				first = first >> 1
				last = (last >> 1) - 1
			return ret
	mod = 998244353
	N = int(input())
	info = []
	X = []
	for _ in range(N):
		(x, d) = map(int, input().split())
		info.append((x, x + d))
		X.append(x)
	info.sort(key=lambda p: p[0])
	X.sort()
	segtree = SegTree(N + 1)
	for i in range(N):
		segtree.update(i + 1, info[i][1])
	dp = [0] * (N + 1)
	dp[-1] = 1
	for i in range(N - 1, -1, -1):
		(l, r) = info[i]
		j = bisect_left(X, r)
		rmax = segtree.query(i + 1, j)
		segtree.update(i + 1, rmax)
		j2 = bisect_left(X, rmax)
		dp[i] = (dp[i + 1] + dp[j2]) % mod
	print(dp[0])
main()


import sys
input = sys.stdin.readline
mod = 998244353
N = int(input())
XD = [tuple(map(int, input().split())) for _ in range(N)]
XD.sort(key=lambda x: x[0])
children = [[] for _ in range(N)]
stack = []
for (i, (x, d)) in list(enumerate(XD))[::-1]:
	while stack and stack[-1][0] < x + d:
		(y, j) = stack.pop()
		children[i].append(j)
	stack.append((x, i))
val = [0] * N
for i in range(N)[::-1]:
	res = 1
	for j in children[i]:
		res = res * val[j] % mod
	val[i] = res + 1
ans = 1
for (x, i) in stack:
	ans = ans * val[i] % mod
print(ans)


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)


import sys
input = lambda : sys.stdin.readline().rstrip()
M = 998244353
n = int(input())
xs = [0] * n
ds = [0] * n
for i in range(n):
	(x, d) = (int(c) for c in input().split())
	ds[i] = d
	xs[i] = (x, i)
import sys
sys.setrecursionlimit(max(1000, n))
xs.sort()
index = [x[1] for x in xs]
xs = [x[0] for x in xs]
ds = [ds[ind] for ind in index]

def _sub(i):
	if i == n - 1:
		return (2, n)
	res = 1
	ind = i + 1
	while True:
		if xs[i] + ds[i] <= xs[ind]:
			break
		(o, ind) = _sub(ind)
		res *= o
		res %= M
		if ind >= n:
			break
	return (res + 1, ind)
out = []
done = 0
while True:
	(o, done) = _sub(done)
	out.append(o)
	if done >= n:
		break
result = 1
for o in out:
	result *= o
	result %= M
print(result)


import sys
from operator import itemgetter
(n, *xd) = 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])


import math, string, itertools, fractions, heapq, collections, re, array, bisect, sys, copy, functools
import time, random
sys.setrecursionlimit(10 ** 7)
inf = 10 ** 20
eps = 1.0 / 10 ** 10
mod = 10 ** 9 + 7
mod2 = 998244353
dd = [(-1, 0), (0, 1), (1, 0), (0, -1)]
ddn = [(-1, 0), (-1, 1), (0, 1), (1, 1), (1, 0), (1, -1), (0, -1), (-1, -1)]

def LI():
	return list(map(int, sys.stdin.readline().split()))

def LLI():
	return [list(map(int, l.split())) for l in sys.stdin.readlines()]

def LI_():
	return [int(x) - 1 for x in sys.stdin.readline().split()]

def LF():
	return [float(x) for x in sys.stdin.readline().split()]

def LS():
	return sys.stdin.readline().split()

def I():
	return int(sys.stdin.readline())

def F():
	return float(sys.stdin.readline())

def S():
	return input()

def pf(s):
	return print(s, flush=True)

def pe(s):
	return print(str(s), file=sys.stderr)

def JA(a, sep):
	return sep.join(map(str, a))

def JAA(a, s, t):
	return s.join((t.join(map(str, b)) for b in a))

class Seg:

	def __init__(self, na, default, func):
		if isinstance(na, list):
			n = len(na)
		else:
			n = na
		i = 1
		while 2 ** i <= n:
			i += 1
		self.D = default
		self.H = i
		self.N = 2 ** i
		if isinstance(na, list):
			self.A = [default] * self.N + na + [default] * (self.N - n)
			for i in range(self.N - 1, 0, -1):
				self.A[i] = func(self.A[i * 2], self.A[i * 2 + 1])
		else:
			self.A = [default] * (self.N * 2)
		self.F = func

	def find(self, i):
		return self.A[i + self.N]

	def update(self, i, x):
		i += self.N
		self.A[i] = x
		while i > 1:
			i = i // 2
			self.A[i] = self.merge(self.A[i * 2], self.A[i * 2 + 1])

	def merge(self, a, b):
		return self.F(a, b)

	def total(self):
		return self.A[1]

	def query(self, a, b):
		A = self.A
		l = a + self.N
		r = b + self.N
		res = self.D
		while l < r:
			if l % 2 == 1:
				res = self.merge(res, A[l])
				l += 1
			if r % 2 == 1:
				r -= 1
				res = self.merge(res, A[r])
			l >>= 1
			r >>= 1
		return res

def main():
	n = I()
	xd = sorted([LI() for _ in range(n)])
	xa = [x for (x, _) in xd] + [inf]
	r = [0] * n + [1]

	def f(a, b):
		if a > b:
			return a
		return b
	seg = Seg(n + 1, 0, f)
	for i in range(n - 1, -1, -1):
		(x, d) = xd[i]
		xi = bisect.bisect_left(xa, x + d)
		qi = seg.query(i, xi)
		if qi > xi:
			xi = qi
		seg.update(i, xi)
		r[i] = (r[i + 1] + r[xi]) % mod2
	return r[0]
print(main())


n = int(input())
l = [tuple(map(int, input().split())) for _ in range(n)] + [(1 << 31, 0)]
mod = 998244353
l.sort()
st = [n]
dp = [0] * n + [1]
for i in range(n - 1, -1, -1):
	(x, d) = l[i]
	v = x + d
	while l[st[-1]][0] < v:
		st.pop()
	dp[i] = (dp[i + 1] + dp[st[-1]]) % mod
	st.append(i)
print(dp[0])


import sys
input = sys.stdin.readline
N = int(input())
robot = []
for i in range(N):
	(x, d) = map(int, input().split())
	robot.append((x, d))
mod = 998244353
robot.sort()
move = [i for i in range(0, N)]
for i in range(0, N):
	(x, d) = robot[i]
	start = i
	end = N - 1
	while end - start > 1:
		test = (end + start) // 2
		if x + d > robot[test][0]:
			start = test
		else:
			end = test
	if x + d > robot[end][0]:
		move[i] = end
	else:
		move[i] = start
n = N

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

def init(init_val):
	for i in range(n):
		seg[i + num - 1] = init_val[i]
	for i in range(num - 2, -1, -1):
		seg[i] = segfunc(seg[2 * i + 1], seg[2 * i + 2])

def update(k, x):
	k += num - 1
	seg[k] = x
	while k:
		k = (k - 1) // 2
		seg[k] = segfunc(seg[k * 2 + 1], seg[k * 2 + 2])

def query(p, q):
	if q <= p:
		return ide_ele
	p += num - 1
	q += num - 2
	res = ide_ele
	while q - p > 1:
		if p & 1 == 0:
			res = segfunc(res, seg[p])
		if q & 1 == 1:
			res = segfunc(res, seg[q])
			q -= 1
		p = p // 2
		q = (q - 1) // 2
	if p == q:
		res = segfunc(res, seg[p])
	else:
		res = segfunc(segfunc(res, seg[p]), seg[q])
	return res
ide_ele = 0
num = 2 ** (n - 1).bit_length()
seg = [ide_ele] * 2 * num
chain = [i for i in range(N)]
for _ in range(0, N):
	i = N - 1 - _
	if move[i] == i:
		chain[i] = i
		update(i, chain[i])
	else:
		chain[i] = query(i + 1, move[i] + 1)
		update(i, chain[i])
dp = [0 for i in range(0, N + 1)]
dp[N] = 1
for j in range(0, N):
	i = N - 1 - j
	if chain[i] == i:
		dp[i] = 2 * dp[i + 1] % mod
	else:
		dp[i] = (dp[i + 1] + dp[chain[i] + 1]) % mod
print(dp[0])


import sys
input = sys.stdin.readline

class SegTree:

	def __init__(self, l):
		emp = -1
		N = len(l)
		n = N
		layer = 1
		bottom = 1
		while n > 1:
			n = n / 2
			layer += 1
			bottom *= 2
		L = [emp] * (2 * bottom - 1)
		for i in range(N):
			L[bottom - 1 + i] = l[i]
		for i in range(bottom - 2, -1, -1):
			L[i] = max(L[2 * i + 1], L[2 * i + 2])
		self.tree = L
		self.bottom = bottom
		self.layer = layer
		self.emp = emp

	def add(self, index, num):
		x = self.bottom + index - 1
		self.tree[x] += num
		for _ in range(self.layer - 1):
			x = (x - 1) // 2
			self.tree[x] = max(self.tree[2 * x + 1], self.tree[2 * x + 2])

	def segment(self, l, r):
		s = -1
		L = self.bottom + l
		R = self.bottom + r
		while L < R:
			if L & 1:
				s = max(s, self.tree[L - 1])
				L += 1
			if R & 1:
				R -= 1
				s = max(s, self.tree[R - 1])
			L //= 2
			R //= 2
		return s
INF = 998244353
n = int(input())
l = []
for i in range(n):
	(x, d) = map(int, input().split())
	l.append((x, d))
l.sort()
x = []
d = []
for i in l:
	x.append(i[0])
	d.append(i[1])
dp = [1]
Sum = [1]
import bisect
t = [0] * n
t = SegTree(t)
for i in range(n):
	y = x[n - 1 - i] + d[n - 1 - i]
	m = bisect.bisect_left(x, y)
	z = t.segment(n - 1 - i, m)
	m = max(m, z)
	t.add(n - 1 - i, m)
	dp.append(Sum[n - m])
	s = (Sum[-1] + dp[-1]) % INF
	Sum.append(s)
print(Sum[-1])


import sys
input = sys.stdin.readline
from bisect import bisect_left

class SegmentTree:

	def __init__(self, param, default, func):
		if isinstance(param, list):
			n = len(param)
		else:
			n = param
		self.d = default
		self.leaf = 1 << (n - 1).bit_length()
		if isinstance(param, list):
			self.tree = [default] * (self.leaf - 1) + param + [default] * (self.leaf - n)
			for i in range(self.leaf - 2, -1, -1):
				self.tree[i] = func(self.tree[i * 2 + 1], self.tree[i * 2 + 2])
		else:
			self.tree = [default] * (self.leaf * 2 - 1)
		self.f = func

	def find(self, i):
		return self.tree[i + self.leaf - 1]

	def update(self, idx, a):
		idx += self.leaf - 1
		self.tree[idx] = a
		while idx:
			idx = idx - 1 >> 1
			self.tree[idx] = self.merge(self.tree[idx * 2 + 1], self.tree[idx * 2 + 2])

	def merge(self, a, b):
		return self.f(a, b)

	def get_top(self):
		return self.tree[0]

	def query(self, a, b):
		T = self.tree
		(l, r) = (a + self.leaf - 1, b + self.leaf - 1)
		res = self.d
		while l < r:
			if not l % 2:
				res = self.merge(res, T[l])
				l += 1
			if not r % 2:
				r -= 1
				res = self.merge(res, T[r])
			l >>= 1
			r >>= 1
		return res

def main():
	mod = 998244353
	n = int(input())
	XD = [list(map(int, input().split())) for _ in range(n)]
	XD.sort()
	X = [x for (x, d) in XD]
	seg = SegmentTree(n, -1, max)
	DP = [0] * (n + 1)
	DP[-1] = 1
	for i in reversed(range(n)):
		(x, d) = XD[i]
		j = bisect_left(X, x + d)
		r = max(i, seg.query(i + 1, j))
		seg.update(i, r)
		DP[i] = (DP[i + 1] + DP[r + 1]) % mod
	print(DP[0])
main()