Problem:
Score : 600 points

Problem Statement

There are N robots numbered 1 to N placed on a number line. Robot i is placed at coordinate X_i. When activated, it will travel the distance of D_i in the positive direction, and then it will be removed from the number line. All the robots move at the same speed, and their sizes are ignorable.

Takahashi, who is a mischievous boy, can do the following operation any number of times (possibly zero) as long as there is a robot remaining on the number line.

Choose a robot and activate it. This operation cannot be done when there is a robot moving.

While Robot i is moving, if it touches another robot j that is remaining in the range [X_i, X_i + D_i) on the number line, Robot j also gets activated and starts moving. This process is repeated recursively.

How many possible sets of robots remaining on the number line are there after Takahashi does the operation some number of times? Compute this count modulo 998244353, since it can be enormous.

Constraints

1 \leq N \leq 2 \times 10^5

-10^9 \leq X_i \leq 10^9

1 \leq D_i \leq 10^9

X_i \neq X_j (i \neq j)

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
X_1 D_1
:
X_N D_N

Output

Print the number of possible sets of robots remaining on the number line, modulo 998244353.

Sample Input 1

2
1 5
3 3

Sample Output 1

3

There are three possible sets of robots remaining on the number line: \{1, 2\}, \{1\}, and \{\}.

These can be achieved as follows:

If Takahashi activates nothing, the robots \{1, 2\} will remain.

If Takahashi activates Robot 1, it will activate Robot 2 while moving, after which there will be no robots on the number line. This state can also be reached by activating Robot 2 and then Robot 1.

If Takahashi activates Robot 2 and finishes doing the operation, the robot \{1\} will remain.

Sample Input 2

3
6 5
-1 10
3 3

Sample Output 2

5

There are five possible sets of robots remaining on the number line: \{1, 2, 3\}, \{1, 2\}, \{2\}, \{2, 3\}, and \{\}.

Sample Input 3

4
7 10
-10 3
4 3
-4 3

Sample Output 3

16

None of the robots influences others.

Sample Input 4

20
-8 1
26 4
0 5
9 1
19 4
22 20
28 27
11 8
-3 20
-25 17
10 4
-18 27
24 28
-11 19
2 27
-2 18
-1 12
-24 29
31 29
29 7

Sample Output 4

110

Remember to print the count modulo 998244353.

Solution in Rust (1.15.1) (judge verdict: Accepted)

// https://atcoder.jp/contests/abc158/tasks/abc158_f
//
#![allow(unused_imports)]
use std::io::*;
use std::io::Write;
use std::fmt::*;
use std::str::*;
use std::cmp::*;
use std::collections::*;

// Input macros.
// Original by tanakh: https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8
#[allow(unused_macros)]
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
    ($($r:tt)*) => {
        let s = {
            use std::io::Read;
            let mut s = String::new();
            std::io::stdin().read_to_string(&mut s).unwrap();
            s
        };
        let mut iter = s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
}

#[allow(unused_macros)]
macro_rules! input_inner {
    ($iter:expr) => {};
    ($iter:expr, ) => {};

    ($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($iter, $t);
        input_inner!{$iter $($r)*}
    };

    ($iter:expr, mut $var:ident : $t:tt $($r:tt)*) => {
        let mut $var = read_value!($iter, $t);
        input_inner!{$iter $($r)*}
    };
}

#[allow(unused_macros)]
macro_rules! read_value {
    ($iter:expr, ( $($t:tt),* )) => {
        ( $(read_value!($iter, $t)),* )
    };

    ($iter:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
    };

    ($iter:expr, [ next / $t:tt ]) => {
        {
            let len = read_value!($iter, usize);
            (0..len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
        }
    };

    ($iter:expr, switch) => {
        {
            let ty = read_value!($iter, i32);
            if ty == 1 {
                vec![ty, read_value!($iter, i32), read_value!($iter, i32)]
            } else if ty == 2 {
                vec![ty, read_value!($iter, i32)]
            } else {
                vec![ty, read_value!($iter, i32)]
            }
        }
    };

    ($iter:expr, chars) => {
        read_value!($iter, String).chars().collect::<Vec<char>>()
    };

    ($iter:expr, usize1) => {
        read_value!($iter, usize) - 1
    };

    ($iter:expr, $t:ty) => {
        $iter.next().unwrap().parse::<$t>().expect("Parse error")
    };
}

#[allow(unused_macros)]
macro_rules! read_line {
    ($t:tt) => {
        {
            let mut s = String::new();
            std::io::stdin().read_line(&mut s).unwrap();
            s.trim_right().parse::<$t>().unwrap()
        }
    }
}

#[allow(unused_macros)]
macro_rules! dvec {
    ($t:expr ; $len:expr) => {
        vec![$t; $len]
    };

    ($t:expr ; $len:expr, $($rest:expr),*) => {
        vec![dvec!($t; $($rest),*); $len]
    };
}

#[allow(unused_macros)]
macro_rules! ifv {
    ($t:expr, $a:expr, $b: expr) => {
        if $t { $a } else { $b }
    }
}

#[allow(unused_macros)]
macro_rules! fill {
    ($t:expr, $v:expr) => {
        for i in 0..$t.len() {
            $t[i] = $v;
        }
    };
}

#[allow(unused_macros)]
macro_rules! join {
    ($t:expr, $glue:expr) => {
        $t.into_iter().map(|w| w.to_string()).collect::<Vec<_>>().join($glue)
    };
}

#[allow(unused_macros)]
macro_rules! debug {
    ($($a:expr),*) => {
        println!(concat!($(stringify!($a), " = {:?}, "),*), $($a),*);
    }
}

// ===

// ====

#[derive(Debug, Clone)]
struct Treap<T> {
    root: Link<T>
}

impl<T: Ord + Copy + Debug> Treap<T> {
    fn new() -> Self {
        Treap {
            root: None
        }
    }

    fn push(&mut self, v: T) -> bool {
        if self.contains(v) {
            return false;
        }
        let u = self.root.take();
        self.root = Node::push(u, v);
        true
    }

    fn remove(&mut self, v: T) -> bool {
        Node::remove(&mut self.root, v)
    }

    fn len(&self) -> usize {
        Node::sz(&self.root)
    }

    fn min(&self) -> Option<T> {
        Node::min(&self.root)
    }

    fn max(&self) -> Option<T> {
        Node::max(&self.root)
    }

    //
    // Returns k-th value in the tree (1-indexed).
    //
    fn kth(&mut self, k: usize) -> Option<T> {
        if k == 0 || Node::sz(&self.root) < k {
            None
        } else {
            let (nl, nr) = Node::split_at(self.root.take(), k-1);
            let val = Node::min(&nr);
            self.root = Node::merge(nl, nr);
            val
        }
    }

    fn contains(&self, value: T) -> bool {
        Node::contains(&self.root, value)
    }

    fn peek_less(&self, value: T) -> Option<T> {
        Node::peek_less(&self.root, value)
    }

    fn count_less(&self, value: T) -> usize {
        Node::count_less(&self.root, value)
    }

    fn peek_greater(&self, value: T) -> Option<T> {
        Node::peek_greater(&self.root, value)
    }
}

struct XorShift {
    x: i64,
    y: i64,
    z: i64,
    w: i64
}

impl XorShift {
    fn rotate(&mut self) {
        let t = self.x ^ (self.x << 11);
        self.x = self.y;
        self.y = self.z;
        self.z = self.w;
        self.w = (self.w ^ (self.w >> 19)) ^ (t ^ (t >> 8));
    }

    fn next_i64(&mut self) -> i64 {
        self.rotate();
        self.w
    }
}

static mut RAND: XorShift = XorShift {
    x: 123456789i64,
    y: 362436069i64,
    z: 521288629i64,
    w: 88675123i64
};

fn generate_next() -> i64 {
    let x;
    unsafe {
        x = RAND.next_i64();
    }
    x
}

type Link<T> = Option<Box<Node<T>>>;

#[derive(Debug, Clone)]
struct Node<T> {
    value: T,
    size: usize,
    priority: i64,
    left: Link<T>,
    right: Link<T>,
}

impl<T: Ord + Copy + Debug> Node<T> {
    fn new(value: T) -> Self {
        Node {
            value: value,
            size: 1,
            priority: generate_next(),
            left: None,
            right: None
        }
    }

    fn sz(node: &Link<T>) -> usize {
        match node.as_ref() { // TODO: Remove as_ref() after upgrading above 1.26
            None => 0,
            Some(x) => x.size
        }
    }

    fn calc(node: &mut Link<T>) {
        if let Some(x) = node.as_mut() { // TODO: Remove as_mut() after upgrading above 1.26
            x.size = 1 + Node::sz(&x.left) + Node::sz(&x.right);
        }
    }

    fn merge(left: Link<T>, right: Link<T>) -> Link<T> {
        match (left, right) {
            (None, None) => None,
            (None, x) => x,
            (x, None) => x,
            (Some(l), Some(r)) => {
                if l.priority < r.priority {
                    let mut l = l;
                    l.right = Self::merge(l.right.take(), Some(r));
                    let mut l = Some(l);
                    Node::calc(&mut l);
                    l
                } else {
                    let mut r = r;
                    r.left = Self::merge(Some(l), r.left.take());
                    let mut r = Some(r);
                    Node::calc(&mut r);
                    r
                }
            }
        }
    }

    fn min(now: &Link<T>) -> Option<T> {
        match now.as_ref() { // TODO: Remove as_ref() after upgrading above 1.26
            None    => None,
            Some(x) => {
                match x.left.as_ref() { // TODO: Remove as_ref() after upgrading above 1.26
                    None    => Some(x.value),
                    Some(_) => Self::min(&x.left)
                }
            }
        }
    }

    fn max(now: &Link<T>) -> Option<T> {
        match now.as_ref() { // TODO: Remove as_ref() after upgrading above 1.26
            None    => None,
            Some(x) => {
                match x.right.as_ref() { // TODO: Remove as_ref() after upgrading above 1.26
                    None    => Some(x.value),
                    Some(_) => Self::max(&x.right)
                }
            }
        }
    }

    fn contains(now: &Link<T>, value: T) -> bool {
        match now.as_ref() { // TODO: Remove as_ref() after upgrading above 1.26
            None => false,
            Some(x) => {
                match value.cmp(&x.value) {
                    Ordering::Less    => Self::contains(&x.left, value),
                    Ordering::Equal   => true,
                    Ordering::Greater => Self::contains(&x.right, value)
                }
            }
        }
    }

    fn count_less(now: &Link<T>, value: T) -> usize {
        match now.as_ref() { // TODO: Remove as_ref() after upgrading above 1.26
            None => 0,
            Some(x) => {
                match value.cmp(&x.value) {
                    Ordering::Less | Ordering::Equal => {
                        Self::count_less(&x.left, value)
                    },
                    Ordering::Greater => {
                        let w = Self::count_less(&x.right, value);
                        Node::sz(&x.left) + 1 + w
                    }
                }
            }
        }
    }

    fn peek_less(now: &Link<T>, value: T) -> Option<T> {
        match now.as_ref() { // TODO: Remove as_ref() after upgrading above 1.26
            None => None,
            Some(x) => {
                match value.cmp(&x.value) {
                    Ordering::Less | Ordering::Equal => {
                        Self::peek_less(&x.left, value)
                    },
                    Ordering::Greater => {
                        let w = Self::peek_less(&x.right, value);
                        if w == None {
                            Some(x.value)
                        } else {
                            Some(max(w.unwrap(), x.value))
                        }
                    }
                }
            }
        }
    }

    fn peek_greater(now: &Link<T>, value: T) -> Option<T> {
        match now.as_ref() { // TODO: Remove as_ref() after upgrading above 1.26
            None => None,
            Some(x) => {
                match value.cmp(&x.value) {
                    Ordering::Greater | Ordering::Equal => {
                        Self::peek_greater(&x.right, value)
                    },
                    Ordering::Less => {
                        let w = Self::peek_greater(&x.left, value);
                        if w == None {
                            Some(x.value)
                        } else {
                            Some(min(w.unwrap(), x.value))
                        }
                    }
                }
            }
        }
    }

    fn split_at(now: Link<T>, k: usize) -> (Link<T>, Link<T>) {
        match now {
            None => (None, None),
            Some(x) => {
                let mut x = x;
                let lsz = Self::sz(&x.left);
                if k <= lsz {
                    let (nl, nr) = Self::split_at(x.left.take(), k);
                    x.left = nr;
                    let mut x = Some(x);
                    Node::calc(&mut x);
                    (nl, x)
                } else {
                    let (nl, nr) = Self::split_at(x.right.take(), k-1-lsz);
                    x.right = nl;
                    let mut x = Some(x);
                    Node::calc(&mut x);
                    (x, nr)
                }
            },
        }
    }

    fn split_by(now: Link<T>, v: T) -> (Link<T>, Link<T>) {
        match now {
            None => (None, None),
            Some(x) => {
                let mut x = x;
                if v <= x.value {
                    let (nl, nr) = Self::split_by(x.left.take(), v);
                    x.left = nr;
                    let mut x = Some(x);
                    Node::calc(&mut x);
                    (nl, x)
                } else {
                    let (nl, nr) = Self::split_by(x.right.take(), v);
                    x.right = nl;
                    let mut x = Some(x);
                    Node::calc(&mut x);
                    (x, nr)
                }
            },
        }
    }

    fn push(now: Link<T>, new_value: T) -> Link<T> {
        let new_node = Some(Box::new(Node::new(new_value)));
        let (left, right) = Self::split_by(now, new_value);
        Self::merge(Self::merge(left, new_node), right)
    }

    fn remove(now: &mut Link<T>, target_value: T) -> bool {
        let mut both_none = false;
        let w = match now.as_mut() { // TODO: Remove as_mut() after upgrading above 1.26
            None => false,
            Some(x) => {
                if target_value < x.value {
                    Self::remove(&mut x.left, target_value)
                } else if x.value < target_value {
                    Self::remove(&mut x.right, target_value)
                } else {
                    let new_link = Self::merge(x.left.take(), x.right.take());
                    if let Some(node) = new_link {
                        *x = node;
                    } else {
                        both_none = true;
                    }
                    true
                }
            }
        };
        Node::calc(now);
        if both_none {
            now.take();
        }
        w
    }
}

// ====

// ====

use std::rc::Rc;
type Merger<T> = Rc<Fn(T, T) -> T>;

struct SegmentTree<T> {
    n: usize,
    default: T,
    bottom_offset: usize,
    data: Vec<T>,
    merger: Merger<T>,
}

impl<T: Debug + Copy + Eq> SegmentTree<T> {
    fn new(n: usize, initial: T, merger: Merger<T>) -> Self {
        let z = (8u32 * std::mem::size_of::<usize>() as u32) - n.leading_zeros();
        let size = (1<<z) as usize;
        SegmentTree {
            n: size*2,
            default: initial,
            bottom_offset: size,
            data: vec![initial; size*2],
            merger: merger,
        }
    }

    /// Change single position [i, i+1) to value v.
    fn set(&mut self, i: usize, v: T) {
        let mut idx = self.bottom_offset + i;
        self.data[idx] = v;
        while idx >= 1 {
            idx /= 2;
            self.data[idx] = (self.merger)(self.data[idx*2], self.data[idx*2+1]);
        }
    }

    /// Get single position value.
    fn get(&mut self, i: usize) -> T {
        self.data[self.bottom_offset+i]
    }

    /// Apply merge with v to single position [i, i+1).
    fn apply(&mut self, i: usize, v: T) {
        let mut idx = self.bottom_offset + i;
        while idx >= 1 {
            self.data[idx] = (self.merger)(self.data[idx], v);
            idx /= 2;
        }
    }

    /// Compute value [i, j).
    fn compute_range(&self, mut i: usize, mut j: usize) -> T {
        if i >= j {
            return self.default;
        }
        let mut result_left = self.default;
        let mut result_right = self.default;
        i += self.bottom_offset;
        j += self.bottom_offset;
        while i != j {
            if i & 1 == 1 {
                result_left = (self.merger)(result_left, self.data[i]);
                i += 1;
            }
            if j & 1 == 1 {
                j -= 1;
                result_right = (self.merger)(self.data[j], result_right);
            }
            i >>= 1;
            j >>= 1;
        }
        (self.merger)(result_left, result_right)
    }

    fn merge(&mut self, i: usize, j: usize) -> T {
        (self.merger)(self.data[i], self.data[j])
    }

    fn debug_print(&self, from: usize, to: usize) {
        for i in from..to {
            debug!(i, self.data[self.bottom_offset+i]);
        }
        debug!(from, to, self.compute_range(from, to));
    }
}

// ====

const MOD: i64 = 998244353;

fn dfs(now: usize, par: Option<usize>, tree: &Vec<Vec<usize>>) -> i64 {
    let mut w = 1;
    for &to in &tree[now] {
        if Some(to) == par {
            continue;
        }
        w *= dfs(to, Some(now), tree);
        w %= MOD;
    }
    w += 1;
    w % MOD
}

fn main() {
    input! {
        n: usize,
        mut robots: [(i64, i64); n]
    };
    robots.sort();

    let mut rmap = Treap::new();
    for i in 0..n {
        rmap.push((robots[i].0, i));
    }
    let mut seg = SegmentTree::new(n+10, 0, Rc::new(|a,b| max(a,b)));
    for i in 0..n {
        seg.set(i, i);
    }
    let mut to = vec![0; n];
    to[n-1] = n-1;
    for i in (0..n-1).rev() {
        let x = robots[i].0 + robots[i].1;
        let (_, idx) = rmap.peek_less((x, 0)).unwrap();
        to[i] = seg.compute_range(i, idx+1);
        seg.set(i, to[i]);
    }

    let mut tree = vec![vec![]; n];
    let mut pop_cnt = vec![0; n];

    let mut root = vec![];
    let mut stk = VecDeque::new();
    for i in 0..n {
        pop_cnt[to[i]] += 1;
        if stk.len() == 0 {
            stk.push_back(i);
            root.push(i);
        } else {
            let x = *stk.back().unwrap();
            tree[x].push(i);
            stk.push_back(i);
        }
        for k in 0..pop_cnt[i] {
            stk.pop_back();
        }
    }

    let mut way = 1;
    let mut dp = vec![0; n];
    for rt in root {
        way *= dfs(rt, None, &mut tree);
        way %= MOD;
    }
    println!("{}", way);
}