#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <string>
#include <sstream>
#include <complex>
#include <vector>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <map>
#include <set>
#include <functional>
#include <random>

using namespace std;
 
#define mod 998244353
#define FOR(x,to) for(int x=0;x<(to);x++)
#define FORR(x,arr) for(auto& x:arr)
#define ALL(a) (a.begin()),(a.end())
#define ZERO(a) memset(a,0,sizeof(a))
#define MINUS(a) memset(a,0xff,sizeof(a))
#define long long long
inline int rei(){int x;cin>>x;return x;}
inline long rel(){long x;cin>>x;return x;}
inline string res(){string x;cin>>x;return x;}
//------------------------------------------------------- 
class Monoid {
public:
    using t = int;
    static t id() {
        return 0;
    }
    static t op(const t& l, const t& r) {
        return max(l, r);
    }
};
template< typename M >
class SegmentTree {
	using T = typename M::t;
	const int n;
	vector<T> data;
	int size(int n_) {
        int res = 1;
        while (res <= n_) {
			res <<= 1;
		}
        return res;
    }
	public:
    SegmentTree(int n_)
        : n(size(n_)), data(n * 2, M::id()) {}
    SegmentTree(int n_, T v)
        : n(size(n_)), data(n * 2, v) {}
    SegmentTree(const vector<T>& data_)
        : n(size(data_.size())), data(n * 2, M::id()) {
            init(data_);
    }
    void init() {
        for (int i = n - 1; i >= 1; i--) data[i] = M::op(data[i * 2], data[i * 2 + 1]);
    }
    void init(const vector<T>& data_) {
        for (int i = 0; i < (int)data_.size(); i++) data[i + n] = data_[i];
        init();
    }
  	void Update(int k,const T x){
    	k += n;
    	data[k] = x;
    	while(k >>= 1){
      		data[k] = M::op(data[2*k+0],data[2*k+1]);
    	}
  	}
	//[a,b)
  	T Query(int a,int b){
    	T L = M::id(), R = M::id();
    	for(a += n,b += n;a < b;a >>= 1,b >>= 1){
      		if(a & 1) L = M::op(L,data[a++]);
      		if(b & 1) R = M::op(data[--b],R);
    	}
    	return M::op(L,R);
  	}
	T Query(int a){
    	return data[a+n];
  	}
	//[0,bc]がFを満たす最小のbc(>=0)ないなら-1
	int MinSearch(function<bool(T)> F){
		if(!F(data[1])){
			return -1;
		}
    	T L = M::id();
		int a = 1;
		while(a < n){
			if(!F(M::op(L,data[a << 1]))){
				L = M::op(L,data[a << 1]);
				a = (a << 1) + 1;
			}
			else{
				a <<= 1;
			}
		}
    	return a-n;
  	}
	//[v,bc]がFを満たす最小のbc(>=v)ないなら-1
	int MinSearch(int v,function<bool(T)> F){
		int a = v+n;
		T L = data[a];
		if(F(L)){
			return v;
		}
		while(a > 1){
			if((a & 1) == 0){
				if(F(M::op(L,data[a+1]))){
					a++;
					break;
				}
				L = M::op(L,data[a+1]);
			}
			a >>= 1;
		}
		if(a == 1){
			return -1;
		}
		while(a < n){
			if(!F(M::op(L,data[a << 1]))){
				L = M::op(L,data[a << 1]);
				a = (a << 1) + 1;
			}
			else{
				a <<= 1;
			}
		}
    	return a-n;
  	}
};
pair<long,long> Ro[200000];
long DP[200001];
void Calc(){
	int N = rei();
	for(int i=0;i<N;i++){
		long X = rei();
		long D = rei();
		Ro[i] = {X,D};
	}
	sort(Ro,Ro+N);
	SegmentTree<Monoid> Seg(N);
	DP[N] = 1;
	for(int i=N-1;i>=0;i--){
		int bf = i;
		int bl = N-1;
		while(bf != bl){
			long bc = (bf+bl+1)/2;
			if(Ro[i].first+Ro[i].second > Ro[bc].first){
				bf = bc;
			}
			else{
				bl = bc-1;
			}
		}
		int t = bf;
		int tt = max(i,Seg.Query(i,t+1));
		Seg.Update(i,tt);
		DP[i] = (DP[tt+1] + DP[i+1]) % mod;
	}
	cout << DP[0] << endl;
}
int main(int argc,char** argv){
	ios::sync_with_stdio(false), cin.tie(0);
	cout.tie(0); Calc(); return 0;
}

Measured memory_bytes: 7040