#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;

const int MAXN = 2e5+10;
const int MAXL = 19;
int n;
int x[MAXN], d[MAXN];
int cid[MAXN], cd[MAXN], idj[MAXN]; // compressed
int farthest[MAXN];
const int M = 998244353;

int mx[MAXN][MAXL]; // bin jump range max

int par[MAXN]; // right end point parent pointer
vector<int> ch[MAXN]; // the number of children 
ll col[MAXN]; //number of ways to colour segment u if it is definitely not coloured.

ll dfs(int u) {
  if (col[u]!=-1) return col[u];
  //cerr << "@ " << u << " has ch "; for(int v:ch[u]) cerr << v << " "; cerr <<endl;
  ll ans = 1; // empty set of coloured things
  for(int v:ch[u]) {
    ans = (1+dfs(v))*ans%M; // either colour v, or do the dp on uncouloured v
  }
  return col[u] = ans;
}


bool sortx(int a, int b) {
  return x[a] < x[b];
}


int main(){
  cin.tie(0); ios_base::sync_with_stdio(0);
  memset(col, -1, sizeof col);
  cin >> n;
  for(int i=0;i<n;i++) cin >> x[i] >> d[i];
  vector<int> id;
  for(int i=0;i<n;i++) cid[i] = i;
  sort(cid, cid+n, sortx);
  set<pair<int,int>> locs;
  for(int j=0;j<n;j++) {
    int i = cid[j];
    idj[j] = i;
    locs.insert({x[i], j});
  }
  for(int j=0;j<n;j++) { //find the real farthest robot that you touch
    int i = cid[j];
    auto it = locs.lower_bound({x[i]+d[i], -1}); // can be end, can't be begin
    it--;
    cd[j] = it->second; // this is the farthest to the right we can reach
  }
  //for(int j=0;j<n;j++) { cout << j << " " << cd[j] << " " << cid[j] << endl; }
  //
  // OK, now compressed, j, and cd[j]
  // Now do range max with sparse table by solving problem backwards

  for(int j=n-1;j>=0;j--) {
    // range query for max in range (j, cd[j]]
    farthest[j] = cd[j];
    //cerr << "from " << j << " goes to " << cd[j] << " oid " << cid[j] << endl;
    if (cd[j] > j) {// no binary jumping if we don't move
      int l = j+1;
      int r = cd[j]; // get max in range
      int d = r-l+1; // size of range
      int i = 0;
      while((1<<i)<=d) i++;
      i--;
      //cerr << l << " " << i << " "<< r-(1<<i)+1 << " " << i << " " << mx[r-(1<<i)+1][i] <<endl;
      farthest[j] = max(mx[l][i], mx[r-(1<<i)+1][i]);
      //cerr << "RANGE " << l << " to " << r << " has max " << farthest[j] <<endl;
    }
    //cerr << "FARTHEST " << j << " is " << farthest[j] <<endl;


    mx[j][0] = farthest[j];
    for(int i=1;i<MAXL;i++) {
      if (j+(1<<(i-1))<n) {
        mx[j][i] = max(mx[j][i-1], mx[j+(1<<(i-1))][i-1]); //j i is in charge [j, j+2^i)
      }
      else mx[j][i] = mx[j][i-1];
    }
  }

  // OK, now real ranges are found, can have same right end point, but diff left start point.
  // Sweep from left to right to find laminar tree to do dp.
  // id is left index, n is whole range
  memset(par, -1,sizeof par);
  for(int j=0;j<n;j++) {
    int parent = n; // parent for j=0 is whole range
    if (j!=0) { 
      if (farthest[j-1] == j-1) parent = par[j-1]; // left is disjoint, hence has a par
      else parent = j-1; // we are in range left of us.
    }
    // indicate that this is the parent of leftmost int ending here
    if (par[farthest[j]]==-1) par[farthest[j]] = parent; 
    ch[parent].push_back(j);
  }

  cout << dfs(n) <<endl;
}


Measured memory_bytes: 51840