#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

typedef long long ll;

const int INF = 1 << 30;
const int MOD = 998244353;

struct Modint {
  ll val;
  
  Modint (ll _val = 0)
    : val(_val % MOD) {}

  Modint operator+ (Modint other) const {
    return Modint(val + other.val);
  }

  void operator+= (Modint other) {
    val += other.val;
    val %= MOD;
  }

  Modint operator- () const {
    return Modint(MOD - val);
  }

  Modint operator- (Modint other) const {
    return Modint(val + MOD - other.val);
  }

  void operator-= (Modint other) {
    val += MOD - other.val;
    val %= MOD;
  }

  Modint operator* (Modint other) const {
    return Modint(val * other.val);
  }

  void operator*= (Modint other) {
    val *= other.val;
    val %= MOD;
  }

  bool operator== (Modint other) const {
    return val == other.val;
  }

  bool operator!= (Modint other) const {
    return val != other.val;
  }
};

Modint exp (Modint a, int k) {
  if (k == 0) {
    return Modint(1);
  } else if (k % 2 == 0) {
    Modint half = exp(a, k / 2);
    return half * half;
  } else {
    return a * exp(a, k - 1);
  }
}

Modint inv (Modint a) {
  return exp(a, MOD - 2);
}

ostream& operator<< (ostream& out, Modint p) {
  out << p.val;
  return out;
}

class SegTree {
  int length;
  vector<int> tree;
  vector<int> lfend;
  vector<int> rgend;

  void update (int u) {
    tree[u] = max(tree[2 * u], tree[2 * u + 1]);
    if (u / 2 != 0) {
      update(u / 2);
    }
  }
  
public:
  SegTree (int _length = 0) {
    length = 1;
    while (length < _length) {
      length *= 2;
    }

    tree = vector<int> (2 * length, 0);
    lfend = vector<int> (2 * length);
    rgend = vector<int> (2 * length);
    
    for (int i = length; i < 2 * length; i++) {
      lfend[i] = i - length;
      rgend[i] = i - length;
    }

    for (int i = length - 1; i > 0; i--) {
      lfend[i] = lfend[2 * i];
      rgend[i] = rgend[2 * i + 1];
    }
  }

  int query (int ql, int qr, int u = 1) {
    ql = max(ql, lfend[u]);
    qr = min(qr, rgend[u]);

    if (ql == lfend[u] && qr == rgend[u]) {
      return tree[u];
    } else if (ql > qr) {
      return -INF;
    } else {
      return max(query(ql, qr, 2 * u), query(ql, qr, 2 * u + 1));
    }
  }

  void set (int idx, int val) {
    tree[length + idx] = val;
    update((length + idx) / 2);
  }
};

const int MAX_N = 2e5 + 5;

vector<int> adj [MAX_N];
Modint dp [MAX_N];

void dfs (int u) {
  dp[u] = Modint(1);
  for (int nxt : adj[u]) {
    dfs(nxt);
    dp[u] *= dp[nxt];
  }
  dp[u] += 1;
}

int main () {
  ios::sync_with_stdio(false);

  int n;
  cin >> n;

  vector<pair<int, int>> arr (n); // <pos, range>
  for (int i = 0; i < n; i++) {
    cin >> arr[i].first >> arr[i].second;
  }

  sort(arr.begin(), arr.end());

  SegTree seg (n + 5);
  for (int i = n - 1; i >= 0; i--) {
    seg.set(i, i);

    int ans = i;
    for (int k = 1 << 25; k != 0; k /= 2) {
      if (ans + k < n && arr[ans + k].first < arr[i].first + arr[i].second) {
        ans += k;
      }
    }

    int mx = seg.query(i, ans);
    seg.set(i, mx);
  }

  vector<pair<int, int>> stk;
  vector<int> roots;
  for (int i = 0; i < n; i++) {
    pair<int, int> cur = make_pair(i, seg.query(i, i));
    while (!stk.empty() && stk.back().second < cur.first) {
      stk.pop_back();
    }

    if (stk.empty()) {
      roots.push_back(cur.first);
    } else {
      adj[stk.back().first].push_back(cur.first);
    }

    stk.push_back(cur);
  }

  Modint ans (1);
  for (int u : roots) {
    dfs(u);
    ans *= dp[u];
  }

  cout << ans << endl;
}


Measured memory_bytes: 31472