#include <bits/stdc++.h>
using namespace std;

/*-------------------Define Start-------------------*/
typedef bool BL;    					// 布尔类型
typedef char SB;    					// 有符号1字节,8位
typedef unsigned char UB;    			// 无符号1字节,8位
typedef short SW;    					// 有符号短整型,16位
typedef unsigned short UW;    			// 无符号短整型,16位
typedef long SDW;    					// 有符号整型,32位
typedef unsigned long UDW;   			// 无符号整型,32位
typedef long long SLL;    				// 有符号长整型,64位
typedef unsigned long long ULL;			// 无符号长整型,64位
typedef char CH;    					// 单个字符
typedef float R32;    					// 单精度浮点数
typedef double R64;    					// 双精度浮点数

#define Rep(i, n) for (register SDW i = 0; i < (n); ++i)
#define For(i, s, t) for (register SDW i = (s); i <= (t); ++i)
#define rFor(i, t, s) for (register SDW i = (t); i >= (s); --i)
#define foreach(i, c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
#define ms0(a) memset(a,0,sizeof(a))
#define msI(a) memset(a,0x7f,sizeof(a))
#define LOWBIT(x) ((x)&(-x))

#define MP make_pair
#define PB push_back
#define ft first
#define sd second
#define ALL(x) x.begin(),x.end()

#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl

#define lson l , mid , rt << 1 
#define rson mid + 1 , r , rt << 1 | 1

const ULL mod = 998244353;				//常用模数(可根据题目需要修改)
const ULL inf = 0x7fffffff;				//用来表示无限大
const ULL infLL = 0x7fffffffffffffffLL;	//用来表示无限大
const R64 EPS = 1e-8;

// 重载<<操作符，用来打印vector 
template < typename T >
ostream& operator<< (ostream& out, vector< T > vec) {
	foreach(i, vec) {
		if(i != vec.begin()) {
			out << " ";
		}
		out << *i;
	}
    return out;
}

// 浮点数正负零判断
SDW sgn(R64 x) {
	if(fabs(x) < EPS) {
		return 0;
	}
	return x > 0 ? 1 : -1;
}

inline R64 pow2(R64 x) {
	return x * x;
}
/*-------------------Define End-------------------*/

struct Robot{
	SDW X, D; 
	SDW next; // 当激活了这个机器人，它所能连续激活的最远的机器人id的下一个id 
	
	inline BL operator< (const Robot& x) { return X < x.X; }
};

istream& operator>> (istream& in, Robot &x) {
    in >> x.X >> x.D;
    return in;
}

const UDW maxN = 2e5 + 7;
SDW N;
Robot robots[maxN];
SDW dp[maxN];	// dp[i]代表区间[i, N - 1] 有多少种激活方法 
SDW ans;

void input(){
	cin >> N;
	Rep(i, N) {
		cin >> robots[i];
	}
	robots[N].X = inf; 	//设置哨兵 
	robots[N].next = N + 1;
	N++;
}

/*---------------线段树------------------*/ 
SDW st[maxN << 2];
    
inline void pushUp(SDW rt) {
    st[rt] = max(st[rt << 1], st[rt << 1 | 1]);
}

inline void build(SDW l, SDW r, SDW rt) {
    if(l >= r) {
        st[rt] = robots[r - 1].next;
        return;
    }
    SDW mid = (l + r) >> 1;
    build(lson);
    build(rson);
    pushUp(rt);
}

// 单点更新 
inline void update(SDW x, SDW y, SDW l, SDW r, SDW rt) {
    if(l >= r) {
        st[rt] = y;
        return;
    }
    SDW mid = (l + r) >> 1;
    if(x <= mid) update(x, y, lson);
    else update(x, y, rson);
    pushUp(rt);
}

// 区间查询 
inline SDW query(SDW L, SDW R, SDW l, SDW r, SDW rt) {
    if(L <= l && r <= R) return st[rt];
    SDW ret = 0;
    SDW mid = (l + r) >> 1;
    
    if(L <= mid) ret = max(ret, query(L, R, lson));
    if(R > mid) ret = max(ret, query(L, R, rson));
    return ret;
}
/*---------------线段树------------------*/ 

// 计算每个robot的next值 
void getNext() {
	// 先用二分计算机器人的直接next 
	rFor(i, N - 2, 0) {
		SDW L = i + 1;
		SDW R = N - 1;
		
		while(L < R) {
			SDW mid = (L + R) >> 1;
			
			if(robots[mid].X > robots[i].X + robots[i].D - 1) {
				R = mid;
			}
			else {
				L = mid + 1;
			}
		}
		
		robots[i].next = R;
	}
	
	build(1, N, 1); 
	
	// 再计算间接next并更新next值 
	rFor(i, N - 2, 0) {
		//查找区间[i, robots[i].next - 1]上的机器人的最大的next 
		robots[i].next = query(i + 1, robots[i].next, 1, N, 1); // 线段树节点从1开始 
		update(i + 1, robots[i].next, 1, N, 1);
	} 
} 

void solve(){
	sort(robots, robots + N);
	getNext();
	
	dp[N - 1] = 1; 
	rFor(i, N - 2, 0) {
		// 激活机器人x 
		dp[i] = (dp[i] + dp[robots[i].next]) % mod;
		// 不激活机器人x 
		dp[i] = (dp[i] + dp[i + 1]) % mod;
	}
	
	ans = dp[0];
}

void output(){
	cout << ans << endl;
}

int main() {
	input();
	solve();
	output();
	return 0;
}


Measured memory_bytes: 12800