#include <bits/stdc++.h>
#define mid (l + r >> 1)
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
template<class A, class B> ostream& operator <<(ostream& out, const pair<A, B> &p) {
    return out << "(" << p.first << ", " << p.second << ")";
}
template <typename T, size_t N>
ostream& operator <<(ostream& out, const array<T, N>& a) {
  out << "["; bool first = true;
  for (auto& v : a) { out << (first ? "" : ", "); out << v; first = 0;} out << "]";
  return out;
}
template <typename T>
ostream& operator <<(ostream& out, const vector<T>& a) {
  out << "["; bool first = true;
  for (auto& v : a) { out << (first ? "" : ", "); out << v; first = 0;} out << "]";
  return out;
}
template <typename T, class Cmp>
ostream& operator <<(ostream& out, const set<T, Cmp>& a) {
  out << "{"; bool first = true;
  for (auto& v : a) { out << (first ? "" : ", "); out << v; first = 0;} out << "}";
  return out;
}
template <typename U, typename T, class Cmp>
ostream& operator <<(ostream& out, const map<U, T, Cmp>& a) {
  out << "{"; bool first = true;
  for (auto& p : a) { out << (first ? "" : ", "); out << p.first << ":" << p.second; first = 0;} out << "}";
  return out;
}
template<class T> inline void YES(T condition) { 
    if(condition) cout << "YES" << endl;
    else cout << "NO" << endl;
}
template<class T> inline void Yes(T condition) {
    if(condition) cout << "Yes" << endl;
    else cout << "No" << endl;
}
template<class T> T gcd(T a, T b) {
    if(a && b) { return gcd(min(a, b), max(a, b) % min(a, b)); }
    else { return a; }
}
template<class T> T lcm(T a, T b){
    return a / gcd(a, b) * b;
}
static constexpr int MOD = 998244353;
long long qpow(long long a, long long b) {
    if (b == 0) return 1;
    long long res = 1;
    while (b) {
        if (b & 1) res = (res * a) % MOD;
        a = (a * a) % MOD;
        b >>= 1;
    }
    return res;
}

const int maxn = 1000000;
const int INF = (int)2e9 + 7;
int tree[maxn];
int build(int idx, int l, int r) {
    if (l == r) return tree[idx] = -INF;
    return tree[idx] = max(build(idx * 2, l, mid), build(idx * 2 + 1, mid + 1, r));
}
int modify(int idx, int l, int r, int i, int val) {
    if (l == r) return tree[idx] = val;
    if (i <= mid) return tree[idx] = max(tree[idx], modify(idx * 2, l, mid, i, val));
    else return tree[idx] = max(tree[idx], modify(idx * 2 + 1, mid + 1, r, i, val));
}
int query(int idx, int l, int r, int x, int y) {
    int res = -INF;
    if (x <= l && y >= r) return tree[idx];
    if (x <= mid) res = max(res, query(idx * 2, l, mid, x, y));
    if (y > mid) res = max(res, query(idx * 2 + 1, mid + 1, r, x, y));
    return res;
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    int n;
    cin >> n;
    vector<PII> ps(n);
    vector<int> a(n);
    vector<int> b(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        cin >> b[i];
        ps[i] = make_pair(a[i], a[i] + b[i]);
    }
    build(1, 1, n + 1);
    sort(ps.begin(), ps.end());
    // cout << "all:" << ps << endl;
    sort(a.begin(), a.end());
    a.push_back(INF);
    map<int, int> m;
    for (int i = 0; i <= n; i++) m[a[i]] = i;
    vector<LL> dp(n + 1);
    dp[n] = 1;
    for (int i = n - 1; i>= 0; i--) {
        dp[i] = dp[i + 1];
        int last = ps[i].second;
        auto it = lower_bound(a.begin(), a.end(), last);
        int idx = m[*it] - 1;
        // cout << "query range:" << i + 1 << "~" << idx + 1 << endl;
        int cfar = max(last, query(1, 1, n + 1, i + 1, idx + 1));
        // cout << "answer:" << query(1, 1, n + 1, i + 1, idx + 1) << endl;
        modify(1, 1, n + 1, i + 1, cfar);
        auto it2 = lower_bound(a.begin(), a.end(), cfar);
        int idx2 = m[*it2];
        // cout << "add dp[" << idx2 << "]" << endl;
        dp[i] += dp[idx2];
        if (dp[i] >= MOD) dp[i] -= MOD;
        // cout << ps[i] << ":" << dp[i] << endl;
    }
    cout << dp[0] << '\n';

    return 0;
}


Measured memory_bytes: 18416