#include <bits/stdc++.h>

#define fst(t) std::get<0>(t)
#define snd(t) std::get<1>(t)
#define thd(t) std::get<2>(t)
#define unless(p) if(!(p))
#define until(p) while(!(p))

using ll = std::int64_t;
using P = std::tuple<int,int>;

constexpr int INF = 2'000'000'100;
constexpr ll MOD = 998244353;

int N, K;
P LR[200100];
std::vector<int> xs;
ll dp[400100];

template <typename M>
struct SegmentTree{
    using T = typename M::type;

    int numLeaves;
    std::vector<T> data;
    
    SegmentTree(int n){
        numLeaves = 1;
        while(numLeaves < n){
            numLeaves *= 2;
        }
        
        data.resize(numLeaves * 2);
        std::fill(data.begin() + numLeaves, data.end(), M::identity());
        
        for(int i=numLeaves-1;i>0;--i){
            data[i] = M::bop(data[i*2], data[i*2+1]);
        }
    }

    template <typename F>
    SegmentTree(int n, F f){
        numLeaves = 1;
        while(numLeaves < n){
            numLeaves *= 2;
        }

        data.resize(numLeaves * 2);
        for(int i=0;i<n;++i){
            data[i + numLeaves] = std::move(f(i));
        }
        std::fill(data.begin() + numLeaves + n, data.end(), M::identity());

        for(int i=numLeaves-1;i>0;--i){
            data[i] = M::bop(data[i*2], data[i*2+1]);
        }
    }

    void set(int k, T v){
        k += numLeaves;
        data[k] = v;
        
        while(k > 1){
            k /= 2;
            data[k] = M::bop(data[k*2], data[k*2+1]);
        }
    }
    
    T product(int l, int r){
        l += numLeaves;
        r += numLeaves;
        
        T pl = M::identity(), pr = M::identity();
        for(;l<r;l/=2,r/=2){
            if(l & 1){
                pl = M::bop(pl, data[l]);
                l += 1;
            }
            if(r & 1){
                r -= 1;
                pr = M::bop(data[r], pr);
            }
        }
        
        return M::bop(pl, pr);
    }
    
    T at(int i){
        return data[i + numLeaves];
    }
};

struct M{
    using type = int;
    static type identity(){
        return 0;
    }
    static type bop(type &m1, type &m2){
        return std::max(m1, m2);
    }
};

SegmentTree<M> seg(400100);

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

  std::cin >> N;

  xs.resize(2 * N + 1);
  
  for(int i=0;i<N;++i){
      int x, d;
      std::cin >> x >> d;

      int l = x, r = x + d;
      LR[i] = std::make_tuple(l, r);
      xs[i*2] = l;
      xs[i*2+1] = r;
  }

  xs[2*N] = INF;

  std::sort(LR, LR + N);

  std::sort(xs.begin(), xs.end());
  xs.erase(std::unique(xs.begin(), xs.end()), xs.end());

  K = xs.size();

  int pr_l2 = K - 1;

  for(int i=N-1;i>=0;--i){
      int l, r;
      std::tie(l, r) = LR[i];

      int l2 = std::lower_bound(xs.begin(), xs.end(), l) - xs.begin(),
          r2 = std::lower_bound(xs.begin(), xs.end(), r) - xs.begin();

      int nxt;
      
      if(l2 <= pr_l2 && pr_l2 < r2){
          nxt = seg.product(l2, r2);
      }else{
          nxt = pr_l2;
      }

      seg.set(l2, nxt);

      // std::cout << i << ", " << l2 << ", " << nxt << std::endl;

      pr_l2 = l2;
  }

  dp[0] = 1;

  for(int i=0;i<N;++i){
      int l;
      std::tie(l, std::ignore) = LR[i];
      
      int l2 = std::lower_bound(xs.begin(), xs.end(), l) - xs.begin();

      int nxt_l2;

      if(i + 1 < N){
          int nxt_l;
          std::tie(nxt_l, std::ignore) = LR[i+1];

          nxt_l2 = std::lower_bound(xs.begin(), xs.end(), nxt_l) - xs.begin();
      }else{
          nxt_l2 = K - 1;
      }

      dp[nxt_l2] = (dp[nxt_l2] + dp[l2]) % MOD;

      int nxt = seg.at(l2);
      dp[nxt] = (dp[nxt] + dp[l2]) % MOD;
  }


  // for(int i=0;i<K;++i){
  //     std::cout << i << ", " << dp[i] << std::endl;
  // }

  ll res = dp[K-1];
  std::cout << res << std::endl;
}


Measured memory_bytes: 10624