#define _CRT_SECURE_NO_WARNINGS
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma comment(linker, "/stack:200000000")
#include <bits/stdc++.h>
#define SIZE 200005
#define rep(i, a, b) for (int i = a; i <= b; ++i)
#define mp make_pair
#define ll long long
#define int long long
using namespace std;
void io() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); }
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e5 + 10;
int nxt[N], tmp[N];
int suf[N];
struct Point {
	int x, d;
	Point() {}
	Point(int _x, int _d) :x(_x), d(_d) {};
	bool operator < (const Point a)const {
		return x < a.x;
	}
}a[N];

namespace Segment {
	typedef int LL;
	const int maxn = 400005;
	const LL inf = -1; //为lazy不用修改的值
	LL tree[maxn << 2], lazy[maxn << 2];
	void build(int root, int left, int right) {
		lazy[root] = inf;
		if (left == right) {
			tree[root] = tmp[left];
			return;
		}
		int mid = (left + right) >> 1;
		build(root << 1, left, mid);
		build(root << 1 | 1, mid + 1, right);
		tree[root] = max(tree[root << 1], tree[root << 1 | 1]);
		//operation，可更改
	}
	void pushdown(int root, int left, int right) {
		//operation，均要修改！！！！！！！！！！
		if (lazy[root] == inf)
			return;
		int mid = (left + right) >> 1;
		tree[root << 1] = max(tree[root << 1], lazy[root]);
		tree[root << 1 | 1] = max(tree[root < 1 | 1], lazy[root]);
		lazy[root << 1] = max(lazy[root << 1], lazy[root]);
		lazy[root << 1 | 1] = max(lazy[root << 1 | 1], lazy[root]);
		lazy[root] = inf;
	}
	void add(int root, int left, int right, int stdl, int stdr, LL val) {
		if (left >= stdl && right <= stdr) {
			tree[root] = max(tree[root], val);
			lazy[root] = max(lazy[root], val); //operation，可更改
			return;
		}
		pushdown(root, left, right);
		int mid = (left + right) >> 1;
		if (stdl <= mid)
			add(root << 1, left, mid, stdl, stdr, val);
		if (stdr > mid)
			add(root << 1 | 1, mid + 1, right, stdl, stdr, val);
		tree[root] = max(tree[root << 1], tree[root << 1 | 1]);
		//operation，可更改
	}
	LL query(int root, int left, int right, int stdl, int stdr) {
		if (left >= stdl && right <= stdr)
			return tree[root];
		pushdown(root, left, right);
		int mid = (left + right) >> 1;
		LL res = inf;
		if (stdl <= mid)
			res = max(res, query(root << 1, left, mid, stdl, stdr));
		if (stdr > mid)
			res = max(res, query(root << 1 | 1, mid + 1, right, stdl, stdr));
		//operation，可更改
		return res;
	}
}
using namespace Segment;

int dp[N][2];
const int P = 998244353;
signed main() {
	io(); int n; cin >> n;
	build(1, 1, n);
	for (int i = 1; i <= n; i++) {
		cin >> a[i].x >> a[i].d;
		nxt[i] = suf[i] = i;
	}
	sort(a + 1, a + 1 + n);
	/*cout << '\n';
	rep(i, 1, n) cout << a[i].x << ' ' << a[i].d << '\n';
	cout << '\n';*/
	for (int i = n - 1; i >= 1; i--) {
		nxt[i] = lower_bound(a + 1, a + 1 + n, Point(a[i].x + a[i].d, 0)) - a - 1;
		nxt[i] = max(query(1, 1, n, i, nxt[i]), nxt[i]);
		add(1, 1, n, i, i, nxt[i]);
		suf[i] = max(suf[i + 1], nxt[i]);
		//cout << i << ':' << nxt[i] << endl;
	}
	//dp[n][0] = dp[n][1] = 1;
	////cout << '\n';
	//for (int i = n - 1; i >= 1; i--) {
	//	dp[i][0] = (dp[i + 1][0] + dp[i + 1][1]) % P;
	//	if (nxt[i] != i)
	//		dp[i][1] = dp[nxt[i]][1];
	//	else
	//		dp[i][1] = dp[i][0];
	//	//cout << dp[i][0] << ' ' << dp[i][1] << endl;
	//}
	//
	dp[n][0] = dp[n][1] = 1;
	for (int i = n - 1; i >= 1; i--) {
		dp[i][0] = (dp[i + 1][0] + dp[i + 1][1]) % P;
		if (nxt[i] != i)
			dp[i][1] = dp[nxt[i]][1];
		else
			dp[i][1] = dp[i][0];
		//cout << dp[i][0] << ' ' << dp[i][1] << endl;
	}
	int ans = dp[1][0] + dp[1][1];
	ans %= P;
	cout << ans;
}
/*
20
-8 1
26 4
0 5
9 1
19 4
22 20
28 27
11 8
-3 20
-25 17
10 4
-18 27
24 28
-11 19
2 27
-2 18
-1 12
-24 29
31 29
29 7
*/

/*
5
20 1
19 2
14 
*/

Measured memory_bytes: 23936