#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 200200;
const int Mod = 998244353;
const int Inf = 2e9;

struct Robot
{
    int x, D;

    Robot(int x = 0, int D = 0) : x(x), D(D) {}

    void Read()
    {
        scanf("%d%d", &x, &D);
    }

    bool operator < (const Robot& Other) const
    {
        return x < Other.x;
    }

    bool operator == (const Robot& Other) const
    {
        return x == Other.x;
    }
};

template <typename type>
struct SegmentTreeWithoutLazyPropagation
{
    #define Miid ((L + R) >> 1)
    #define Leeft (Node << 1)
    #define Riight (Node << 1 | 1)

    private : const type E = -Inf;      /// identity element        /// Check this
    private : static const int Nax = 4 * N;                         /// Check this

    private : int n;    /// Array length
    private : type Tree[Nax];

    public : SegmentTreeWithoutLazyPropagation(int n = 0) : n(n)
    {
        for(int Node = 0; Node < Nax; Node++)
            Tree[Node] = E;
    }

    private : type Unite(type x, type y)    /// Check this
    {
        return max(x, y);
    }

    private : void Merge(int Node)
    {
        Tree[Node] = Unite(Tree[Leeft], Tree[Riight]);
    }

    public : void Build(const vector <type>& a)
    {
        Clear();
        n = a.size();
        Build(a, 1, 0, n - 1);
    }

    private : void Build(const vector <type>& a, int Node, int L, int R)
    {
        Tree[Node] = E;

        if(L == R)  return void(Tree[Node] = a[L]);

        Build(a, Leeft, L, Miid);
        Build(a, Riight, Miid + 1, R);

        Merge(Node);
    }

    public : void Update(int i, type x)
    {
        if(n <= 0)  return ;
        Update(i, x, 1, 0, n - 1);
    }

    private : void Update(int i, type x, int Node, int L, int R)
    {
        if(i < L || R < i)      return ;
        if(L == R)              return void(Tree[Node] = x);    /// Check This

        Update(i, x, Leeft, L, Miid);
        Update(i, x, Riight, Miid + 1, R);

        Merge(Node);
    }

    public : type Query(int i, int j)
    {
        if(n <= 0 || i > j) return E;
        return Query(i, j, 1, 0, n - 1);
    }

    private : type Query(int i, int j, int Node, int L, int R)
    {
        if(j < L || R < i)      return E;
        if(i <= L && R <= j)    return Tree[Node];

        return Unite(Query(i, j, Leeft, L, Miid), Query(i, j, Riight, Miid + 1, R));
    }

    public : void Clear()
    {
        for(int Node = 0; Node <= 4 * n; Node++)
            Tree[Node] = E;
        n = 0;
    }
};

Robot a[N];
SegmentTreeWithoutLazyPropagation <int> myTree;

void add_self(int& x, int y)
{
    if((x += y) >= Mod) x -= Mod;
}

int add(int x, int y)
{
    return add_self(x, y), x;
}

int mul(int x, int y)
{
    return (ll) x * y % Mod;
}

int main()
{
    int n;  cin >> n;

    for(int i = 0; i < n; i++)  a[i].Read();

    sort(a, a + n);

    myTree.Build(vector <int> (n));

    for(int i = n - 1; ~i; --i)
    {
        int j = lower_bound(a, a + n, Robot(a[i].x + a[i].D, 0)) - a;
        a[i].D = max(a[i].x + a[i].D, myTree.Query(i + 1, j - 1));
        myTree.Update(i, a[i].D);
    }

    vector <int> Dp(n + 1);
    Dp[n] = 1;

    for(int i = n - 1; ~i; --i)
    {
        int j = lower_bound(a, a + n, Robot(a[i].D, 0)) - a;

        Dp[i] = add(Dp[i + 1], Dp[j]);
    }

    cout << Dp[0] << endl;
}


Measured memory_bytes: 5760