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 (Python):
import sys
import bisect
input = sys.stdin.readline

class SegmentTree:
    def __init__(self, a):
        self.padding = -float('inf')
        self.n = len(a)
        self.N = 2 ** (self.n-1).bit_length()
        self.data = [self.padding]*(self.N-1) + a + [self.padding]*(self.N-self.n)
        for i in range(2*self.N-2, 0, -2):
            self.data[(i-1)//2] = max(self.data[i], self.data[i-1])
    
    def __len__(self):
        return self.n
    
    def update(self, i, x):
        idx = self.N - 1 + i
        self.data[idx] = x
        while idx:
            idx = (idx-1) // 2
            self.data[idx] = max(self.data[2*idx+1], self.data[2*idx+2])
    
    def query(self, i, j):
        
        if i == j:
            return self.data[self.N - 1 + i]
        else:
            idx1 = self.N - 1 + i
            idx2 = self.N - 2 + j 
            result = self.padding
            while idx1 + 1 < idx2:
                if idx1&1 == 0: 
                    result = max(result, self.data[idx1])
                if idx2&1 == 1: 
                    result = max(result, self.data[idx2])
                    idx2 -= 1
                
                idx1 //= 2
                idx2 = (idx2 - 1)//2
            
            if idx1 == idx2:
                result = max(result, self.data[idx1])
            else: 
                result = max(result, self.data[idx1], self.data[idx2])
            
            return result


MOD = 998244353
N = int(input())
XD = [list(map(int, input().split())) for i in range(N)]
XD.sort()

X = [xd[0] for xd in XD]

dp = [0] * (N+1)
dp[-1] = 1
st = SegmentTree([i for i in range(N)])
for i in range(N-1, -1, -1):
  idx = bisect.bisect_left(X, sum(XD[i])) - 1
  if idx > i:
    idx = st.query(i, idx+1)
    st.update(i, idx) 
  dp[i] = (dp[i+1] + dp[idx+1]) % MOD

print(dp[0])

Solution (Python):
import sys
input=sys.stdin.readline
class SegTree:
    def __init__(self, l):
        emp=-1 
        
        N=len(l)
        n=N
        layer=1
        bottom=1
        while n>1:
            n=n/2
            layer+=1
            bottom*=2
        L=[emp]*(2*bottom-1)
        
        for i in range(N):
            L[bottom-1+i]=l[i]
        for i in range(bottom-2,-1,-1):
            L[i]=max(L[2*i+1],L[2*i+2])
        self.tree=L
        self.bottom=bottom
        self.layer=layer
        self.emp=emp

    def add(self,index,num):
        x=self.bottom+index-1
        self.tree[x]+=num
        for _ in range(self.layer-1):
            x=(x-1)//2
            self.tree[x]=max(self.tree[2*x+1],self.tree[2*x+2])

    
    def segment(self,l,r):
        s=-1
        L=self.bottom+l
        R=self.bottom+r
        while L<R:
            if L&1:
                s=max(s,self.tree[L-1])
                L+=1
            if R&1:
                R-=1
                s=max(s,self.tree[R-1])
            L//=2
            R//=2
        return s
INF=998244353
n=int(input())
l=[]
for i in range(n):
    x,d=map(int,input().split())
    l.append((x,d))
l.sort()
x=[]
d=[]
for i in l:
    x.append(i[0])
    d.append(i[1])
dp=[1]
Sum=[1]
import bisect
t=[0]*n
t=SegTree(t)
for i in range(n):
    y=x[n-1-i]+d[n-1-i]
    m=bisect.bisect_left(x,y)
    z=t.segment(n-1-i,m)
    m=max(m,z)
    t.add(n-1-i,m)
    dp.append(Sum[n-m])
    s=(Sum[-1]+dp[-1])%INF
    Sum.append(s)
print(Sum[-1])

Solution (Python):
class SegTree:
    def __init__(self, init_val, ide_ele, seg_func):
        self.segfunc = seg_func
        n = len(init_val)
        self.num = 2**(n-1).bit_length()
        self.ide_ele = ide_ele
        self.seg=[self.ide_ele]*2*self.num
        for i in range(n):
            self.seg[i+self.num-1]=init_val[i]    
        for i in range(self.num-2,-1,-1) :
            self.seg[i]=self.segfunc(self.seg[2*i+1],self.seg[2*i+2]) 
        
    def update(self, k, x):
        k += self.num-1
        self.seg[k] = x
        
        while k+1:
            k = (k-1)//2
            self.seg[k] = self.segfunc(self.seg[k*2+1],self.seg[k*2+2])
        
    def query(self, p, q):
        if q<=p:
            return self.ide_ele
        p += self.num-1
        q += self.num-2
        res=self.ide_ele
        while q-p>1:
            if p&1 == 0:
                res = self.segfunc(res,self.seg[p])
            if q&1 == 1:
                res = self.segfunc(res,self.seg[q])
                q -= 1
            p = p//2
            q = (q-1)//2
        if p == q:
            res = self.segfunc(res,self.seg[p])
        else:
            res = self.segfunc(self.segfunc(res,self.seg[p]),self.seg[q])
        return res
import sys;input=sys.stdin.readline
mod = 998244353
N=int(input())
X = []
Y = []
for _ in range(N):
    x, d = map(int, input().split())
    X.append((x,d))
X.sort(key=lambda x:x[0])
for i, (x, d) in enumerate(X):
    Y.append((2*x,i,0))
    Y.append((2*x+2*d-1,i,1))
Y.sort(key=lambda x:x[0])
C = [0]*N
for x, i, t in Y:
    if t==0:
        j = i
    elif t==1:
        C[i] = j
st = SegTree(C, -1, max)
dp = [1]*(N+1)
for i in range(N-1, -1, -1):
    y=st.query(i, C[i]+1)
    st.update(i, y)
    dp[i] = (dp[i+1]+dp[y+1]) % mod
print(dp[0])

Solution (Python):
import bisect
import operator
import os
import sys
from functools import reduce


class SegmentTree:
    
    def __init__(self, values, op=operator.add):
        """
        :param list values:
        :param callable op: 結合律を満たす二項演算
        """
        self._size = len(values)
        self._op = op
        tree = [None] * self._size * 2
        tree[self._size:] = values[:]
        for i in reversed(range(1, self._size)):
            tree[i] = self._op(tree[i << 1], tree[i << 1 | 1])
        self._tree = tree

    def set(self, i, value):
        """
        values[i] = value
        :param int i:
        :param value:
        """
        i += self._size
        self._tree[i] = value
        i >>= 1
        while i > 0:
            self._tree[i] = self._op(self._tree[i << 1], self._tree[i << 1 | 1])
            i >>= 1

    def add(self, i, value):
        """
        values[i] = values[i]・value
        :param int i:
        :param value:
        """
        new_value = self._op(self._tree[self._size + i], value)
        self.set(i, new_value)

    def get(self, l, r=None):
        """
        [l, r) に op を順番に適用した値
        :param int l:
        :param int|None r:
        """
        if r is None:
            return self._tree[self._size + l]
        ret_l = []
        ret_r = []
        l += self._size
        r += self._size
        while l < r:
            if l & 1:
                ret_l.append(self._tree[l])
                l += 1
            if r & 1:
                r -= 1
                ret_r.append(self._tree[r])
            l >>= 1
            r >>= 1
        return reduce(self._op, ret_l + ret_r)

    def __len__(self):
        return self._size

    def get_values_copy(self):
        return self._tree[self._size:]


if os.getenv("LOCAL"):
    sys.stdin = open("_in.txt", "r")

sys.setrecursionlimit(10 ** 9)
INF = float("inf")
IINF = 10 ** 18
MOD = 998244353

N = int(sys.stdin.buffer.readline())
XD = [list(map(int, sys.stdin.buffer.readline().split())) for _ in range(N)]

XD.sort()
X = [x for x, d in XD]
D = [d for x, d in XD]


st = SegmentTree(list(range(N)), op=max)
for i, (x, d) in reversed(list(enumerate(XD))):
    ri = bisect.bisect_left(X, x + d) - 1
    st.set(i, st.get(i, ri + 1))
R = st.get_values_copy()


dp = [0] * (N + 1)
dp[-1] = 1
for i, r in reversed(list(enumerate(R))):
    
    dp[i] += dp[i + 1]
    
    dp[i] += dp[r + 1]
    dp[i] %= MOD

print(dp[0])

Solution (Python):
import bisect
import operator
import os
import sys
from functools import reduce


class SegmentTree:
    
    def __init__(self, values, op=operator.add):
        """
        :param list values:
        :param callable op: 結合律を満たす二項演算
        """
        self._size = len(values)
        self._op = op
        tree = [None] * self._size * 2
        tree[self._size:] = values[:]
        for i in reversed(range(1, self._size)):
            tree[i] = self._op(tree[i << 1], tree[i << 1 | 1])
        self._tree = tree

    def set(self, i, value):
        """
        values[i] = value
        :param int i:
        :param value:
        """
        i += self._size
        self._tree[i] = value
        i >>= 1
        while i > 0:
            self._tree[i] = self._op(self._tree[i << 1], self._tree[i << 1 | 1])
            i >>= 1

    def add(self, i, value):
        """
        values[i] = values[i]・value
        :param int i:
        :param value:
        """
        new_value = self._op(self._tree[self._size + i], value)
        self.set(i, new_value)

    def get(self, l, r=None):
        """
        [l, r) に op を順番に適用した値
        :param int l:
        :param int|None r:
        """
        if r is None:
            return self._tree[self._size + l]
        ret_l = []
        ret_r = []
        l += self._size
        r += self._size
        while l < r:
            if l & 1:
                ret_l.append(self._tree[l])
                l += 1
            if r & 1:
                r -= 1
                ret_r.append(self._tree[r])
            l >>= 1
            r >>= 1
        return reduce(self._op, ret_l + ret_r)

    def __len__(self):
        return self._size


if os.getenv("LOCAL"):
    sys.stdin = open("_in.txt", "r")

sys.setrecursionlimit(10 ** 9)
INF = float("inf")
IINF = 10 ** 18
MOD = 998244353

N = int(sys.stdin.buffer.readline())
XD = [list(map(int, sys.stdin.buffer.readline().split())) for _ in range(N)]

XD.sort()
X = [x for x, d in XD]
D = [d for x, d in XD]


st = SegmentTree(list(range(N)), op=max)
for i, (x, d) in reversed(list(enumerate(XD))):
    ri = bisect.bisect_left(X, x + d) - 1
    st.set(i, st.get(i, ri + 1))
R = [st.get(i) for i in range(N)]


dp = [0] * (N + 1)
dp[-1] = 1
for i, r in reversed(list(enumerate(R))):
    
    dp[i] += dp[i + 1]
    
    dp[i] += dp[r + 1]
    dp[i] %= MOD

print(dp[0])

Solution (Python):
import sys
sys.setrecursionlimit(10 ** 7)
input = sys.stdin.readline
from bisect import bisect_left

N = int(input())
XD = [[int(i) for i in input().split()] for _ in range(N)]
XD.sort()
MOD = 998244353

def make():
    edge = [[] for _ in range(N)]
    parent = [-1] * N
    MAXIDX = N
    sorted_X = [X for X,_ in XD]
    for i in range(N-1, -1, -1):
        idx = bisect_left(sorted_X, XD[i][0] + XD[i][1])
        for j in range(i+1, min(idx, MAXIDX)):
            if parent[j] < 0:
                parent[j] = i
        if idx >= MAXIDX:
            MAXIDX = i + 1
    for i,par in enumerate(parent):
        if par < 0:
            continue
        edge[par].append(i)
    
    return parent, edge

parent, edge = make()

def cnt(node):
    if not edge[node]:
        return 2

    res = 1
    for v in edge[node]:
        res = (res * cnt(v)) % MOD
    res += 1

    return res % MOD

def main():
    ans = 1
    for i,par in enumerate(parent):
        if par < 0:
            ans = (ans * cnt(i)) % MOD

    print(ans)

if __name__ == "__main__":
    main()

Solution (Python):
import sys
input = sys.stdin.readline

mod = 998244353
N = int(input())
X = []
for _ in range(N):
    x, d = map(int, input().split())
    X.append((x, x + d))

X = sorted(X, key = lambda x: x[0])
L = [(0, -(10**9+1), 10**9+1)]
P = [-1] * (N+1)
for i, (x, y) in enumerate(X):
    while L[-1][2] <= y:
        if L[-1][2] > x and P[i+1] < 0:
            P[i+1] = L[-1][0]
        L.pop()
    if P[i+1] < 0:
        P[i+1] = L[-1][0]
    L.append((i+1, x, y))

C = [[] for _ in range(N+1)]
for i, p in enumerate(P):
    if p >= 0:
        C[p].append(i)

Y = [1] * (N+1)
for i in range(N+1)[::-1]:
    s = 1
    for j in C[i]:
        s = s * (Y[j] + 1) % mod
    Y[i] = s

print(Y[0])

Solution (Python):
n = int(input())
l = [tuple(map(int, input().split())) for _ in range(n)] + [(1<<31, 0)]
mod = 998244353
l.sort()
st = [n]
dp = [0]*n + [1]
for i in range(n-1,-1,-1):
  x,d = l[i]
  v = x + d
  while l[st[-1]][0] < v: st.pop()
  dp[i] = (dp[i+1] + dp[st[-1]]) % mod
  st.append(i)
print(dp[0])

Solution (Python):
mod = 998244353
n = int(input())
l = [tuple(map(int, input().split())) for _ in range(n)] + [(10**10, 0)]
l.sort()
st = [n]
nex = [n]*n
for i in range(n-1,-1,-1):
  x,d = l[i]
  v = x + d
  while l[st[-1]][0] < v: st.pop()
  nex[i] = st[-1]
  st.append(i)
dp = [0]*(n+1)
dp[n] = 1
for i in range(n-1,-1,-1):
  dp[i] = (dp[i+1] + dp[nex[i]]) % mod
print(dp[0])

Solution (Python):





def main():
    from collections import deque, namedtuple
    from operator import attrgetter
    import sys
    input = sys.stdin.readline

    MOD = 998244353

    Robot = namedtuple('Robot', 'x d reach ind')

    N = int(input())

    robots = []
    for ind in range(N):
        X, D = map(int, input().split())
        robots.append(Robot(X, D, X + D, ind))
    robots.sort(key=attrgetter('x'), reverse=True)

    parents = [-1] * N
    to_candidates = deque()
    for robot_from in robots:  
        """
        右端に位置するロボットから順に「起点」と見なしていく
        既出のロボットで有向辺の行き先として一度も設定されていないものが
        to_candidatesにx昇順で溜められている
        to_candidatesに含まれるロボットで「起点」から接触範囲内のものがある限り、
        「起点」から有向辺を張り続ける
        to_candidatesの先頭候補(最も左側に位置する)に対して辺を張れない場合、
        それ以降の候補のxはより遠い座標で辺を張れないので
        「起点」から張れる辺がないとわかる
        すべてのロボットは「起点」から辺を張られてto_candidatesから外れるか
        to_candidatesに残り、グラフ(森)の各木のrootとなる
        """
        while to_candidates:
            robot_to = to_candidates[0]
            if robot_to.x < robot_from.reach:
                parents[robot_to.ind] = robot_from.ind
                to_candidates.popleft()
            else:
                break

        to_candidates.appendleft(robot_from)

    ret = 1
    count = [1] * N
    for robot in robots:  
        par = parents[robot.ind]
        count[robot.ind] += 1
        if ~par:
            count[par] = (count[par] * count[robot.ind]) % MOD
        else:
            ret = (ret * count[robot.ind]) % MOD
            
            
    print(ret)
    return


if __name__ == '__main__':
    main()

Solution (Python):




def main():
    from collections import deque, namedtuple
    from operator import attrgetter
    import sys
    sys.setrecursionlimit(10 ** 7)
    input = sys.stdin.readline

    MOD = 998244353

    Robot = namedtuple('Robot', 'x d reach ind')

    N = int(input())

    robots = []
    for ind in range(N):
        X, D = map(int, input().split())
        robots.append(Robot(X, D, X + D, ind))
    robots.sort(key=attrgetter('x'), reverse=True)

    parents = [-1] * N
    to_candidates = deque()
    for robot_from in robots:  
        """
        右端に位置するロボットから順に「起点」と見なしていく
        既出のロボットで有向辺の行き先として一度も設定されていないものが
        to_candidatesにx昇順で溜められている
        to_candidatesに含まれるロボットで「起点」から接触範囲内のものがある限り、
        「起点」から有向辺を張り続ける
        to_candidatesの先頭候補(最も左側に位置する)に対して辺を張れない場合、
        それ以降の候補のxはより遠い座標で辺を張れないので
        「起点」から張れる辺がないとわかる
        すべてのロボットは「起点」から辺を張られてto_candidatesから外れるか
        to_candidatesに残り、グラフ(森)の各木のrootとなる
        """
        while to_candidates:
            robot_to = to_candidates[0]
            if robot_to.x < robot_from.reach:
                parents[robot_to.ind] = robot_from.ind
                to_candidates.popleft()
            else:
                break

        to_candidates.appendleft(robot_from)

    ret = 1
    count = [1] * N
    for robot in robots:  
        par = parents[robot.ind]
        count[robot.ind] += 1
        if ~par:
            count[par] = (count[par] * count[robot.ind]) % MOD
        else:
            ret = (ret * count[robot.ind]) % MOD
            
            
    print(ret)
    return


if __name__ == '__main__':
    main()

Solution (Python):
from heapq import *
import sys

sys.setrecursionlimit(10 ** 6)
int1 = lambda x: int(x) - 1
p2D = lambda x: print(*x, sep="\n")
def II(): return int(sys.stdin.readline())
def MI(): return map(int, sys.stdin.readline().split())
def LI(): return list(map(int, sys.stdin.readline().split()))
def LLI(rows_number): return [LI() for _ in range(rows_number)]
def SI(): return sys.stdin.readline()[:-1]

def main():
    def dfs(i):
        res = 1
        for j in to[i]:
            res = res * dfs(j) % md
        return res + 1

    md = 998244353
    n = II()
    xd = LLI(n)
    xd.sort(reverse=True)
    to = [[] for _ in range(n)]
    hp = []
    for i, (x, d) in enumerate(xd):
        while hp and hp[0][0] < x + d:
            px, pi = heappop(hp)
            to[i].append(pi)
        heappush(hp, (x, i))
    ans = 1
    while hp:
        _, i = heappop(hp)
        ans = ans * dfs(i) % md
    print(ans)

main()

Solution (Python):

import sys, math, itertools, collections, bisect
input = lambda: sys.stdin.buffer.readline().rstrip().decode('utf-8')
inf = float('inf') ;mod = 998244353
mans = inf ;ans = 0 ;count = 0 ;pro = 1
sys.setrecursionlimit(10**6)

n = int(input())
XD = [(-10**10,inf)]
for i in range(n):
  x,d = map(int,input().split())
  XD.append((x,d))
XD.sort()
visited = [0] * (n+1)
def dfs(node):
  visited[node] = 1
  res = 1
  i = node + 1
  while i < n+1:
    if XD[i][0] < XD[node][0] + XD[node][1]:
      if visited[i]:continue
      pro,i = dfs(i)
      res *= pro
      res %= mod
    else: break
  
  return res + 1 , i
print((dfs(0)[0]-1)%mod)

Solution (Python):
import heapq

mod = 998244353

n = int(input())
robot = [tuple(map(int, input().split())) for _ in range(n)]
robot.sort(reverse=True)
parent = list(range(n))

root = []
for i in range(n):
  x, d = robot[i]
  while root:
    r = heapq.heappop(root)
    if r[0] < x + d:
      parent[r[1]] = i
    else:
      heapq.heappush(root, r)
      break
  heapq.heappush(root, (x, i))
  
count = 1
dp = [1] * n
for i in range(n):
  p = parent[i]
  if p == i:
    count = count * (dp[i] + 1) % mod
  else:
    dp[p] = dp[p] * (dp[i] + 1) % mod
print(count)

Solution (Python):
class SegTree:
    def __init__(self, init_val, ide_ele, seg_func):
        self.segfunc = seg_func
        n = len(init_val)
        self.num = 2**(n-1).bit_length()
        self.ide_ele = ide_ele
        self.seg=[self.ide_ele]*2*self.num
        for i in range(n):
            self.seg[i+self.num-1]=init_val[i]    
        for i in range(self.num-2,-1,-1) :
            self.seg[i]=self.segfunc(self.seg[2*i+1],self.seg[2*i+2]) 
        
    def update(self, k, x):
        k += self.num-1
        self.seg[k] = x
        
        while k+1:
            k = (k-1)//2
            self.seg[k] = self.segfunc(self.seg[k*2+1],self.seg[k*2+2])
        
    def query(self, p, q):
        if q<=p:
            return self.ide_ele
        p += self.num-1
        q += self.num-2
        res=self.ide_ele
        while q-p>1:
            if p&1 == 0:
                res = self.segfunc(res,self.seg[p])
            if q&1 == 1:
                res = self.segfunc(res,self.seg[q])
                q -= 1
            p = p//2
            q = (q-1)//2
        if p == q:
            res = self.segfunc(res,self.seg[p])
        else:
            res = self.segfunc(self.segfunc(res,self.seg[p]),self.seg[q])
        return res
import sys;input=sys.stdin.readline
mod = 998244353
N=int(input())
X = []
Y = []
for _ in range(N):
    x, d = map(int, input().split())
    X.append((x,d))
X.sort(key=lambda x:x[0])
for i, (x, d) in enumerate(X):
    Y.append((2*x,i,0))
    Y.append((2*x+2*d-1,i,1))
Y.sort(key=lambda x:x[0])
C = [0]*N
for x, i, t in Y:
    if t==0:
        j = i
    elif t==1:
        C[i] = j
st = SegTree(C, -1, max)
dp1 = [0]*(N+1)
dp2 = [1]*(N+1)
for i in range(N-1, -1, -1):
    y=st.query(i, C[i]+1)
    st.update(i, y)
    dp1[i] = (dp1[i+1]+dp2[i+1]) % mod
    dp2[i] = (dp1[y+1]+dp2[y+1]) % mod
print((dp1[0]+dp2[0])%mod)

Solution (Python):
import sys
input = sys.stdin.readline

n = int(input())
xd = [list(map(int, input().split())) for _ in range(n)]

mod = 998244353

xd.sort()



def init_max(init_max_val):
    
    for i in range(n):
        seg_max[i+num_max-1]=init_max_val[i]
    
    for i in range(num_max-2,-1,-1) :
        seg_max[i]=max(seg_max[2*i+1],seg_max[2*i+2])

def update_max(k,x):
    k += num_max-1
    seg_max[k] = x
    while k:
        k = (k-1)//2
        seg_max[k] = max(seg_max[k*2+1],seg_max[k*2+2])

def query_max(p,q):
    if q<=p:
        return ide_ele_max
    p += num_max-1
    q += num_max-2
    res=ide_ele_max
    while q-p>1:
        if p&1 == 0:
            res = max(res,seg_max[p])
        if q&1 == 1:
            res = max(res,seg_max[q])
            q -= 1
        p = p//2
        q = (q-1)//2
    if p == q:
        res = max(res,seg_max[p])
    else:
        res = max(max(res,seg_max[p]),seg_max[q])
    return res


ide_ele_max = -1



num_max = 2**(len(str(bin(n-1))) -2)
seg_max=[ide_ele_max]*2*num_max

import bisect
xs = list(map(lambda x: x[0], xd))

ans = [0]*(n+1)
ans[-1] = 1

for i in range(n-1, -1, -1):
    move_r = bisect.bisect_left(xs, sum(xd[i]))
    if(i+1 == move_r):
        update_max(i, i)
    else:
        update_max(i, query_max(i+1, move_r))

    ans[i] = (ans[i+1] + ans[seg_max[i + num_max - 1] + 1]) % mod

print(ans[0])

Solution (Python):
import sys
from bisect import bisect_left
from operator import itemgetter


class SegTreeMax:
    """
    以下のクエリを処理する
    1.update:  i番目の値をxに更新する
    2.get_min: 区間[l, r)の最小値を得る
    """

    def __init__(self, n, INF):
        """
        :param n: 要素数
        :param INF: 初期値（入りうる要素より十分に大きな数）
        """
        n2 = 1 << (n - 1).bit_length()
        self.offset = n2
        self.tree = [INF] * (n2 << 1)
        self.INF = INF

    def initialize(self, arr):
        for i, v in enumerate(arr, start=self.offset):
            self.tree[i] = v
        for i in range(self.offset - 1, 0, -1):
            j = i << 1
            self.tree[i] = max(self.tree[j], self.tree[j + 1])

    def update(self, i, x):
        """
        i番目の値をxに更新
        :param i: index(0-indexed)
        :param x: update value
        """
        i += self.offset
        self.tree[i] = x
        while i > 1:
            y = self.tree[i ^ 1]
            if y >= x:
                break
            i >>= 1
            self.tree[i] = x

    def get_max(self, a, b):
        """
        [a, b)の最大値を得る
        :param a: index(0-indexed)
        :param b: index(0-indexed)
        """
        result = self.INF

        l = a + self.offset
        r = b + self.offset
        while l < r:
            if r & 1:
                result = max(result, self.tree[r - 1])
            if l & 1:
                result = max(result, self.tree[l])
                l += 1
            l >>= 1
            r >>= 1

        return result


n, *xd = map(int, sys.stdin.buffer.read().split())
MOD = 998244353
xd = sorted(zip(xd[0::2], xd[1::2]))
xxx = list(map(itemgetter(0), xd))
ans = [0] * (n + 1)
skip = list(range(1, n + 1))
ans[n] = 1
sgt = SegTreeMax(n + 1, 0)
sgt.initialize(list(range(1, n + 2)))
for i in range(n - 1, -1, -1):
    x, d = xd[i]
    r = x + d
    j = bisect_left(xxx, r)
    k = sgt.get_max(i, j)
    ans[i] = (ans[i + 1] + ans[k]) % MOD
    sgt.update(i, k)
print(ans[0])

Solution (Python):
printn = lambda x: print(x,end='')
inn = lambda : int(input())
inl   = lambda: list(map(int, input().split()))
inm   = lambda:      map(int, input().split())
ins = lambda : input().strip()
DBG = True  and False
BIG = 10**18
R = 998244353

def ddprint(x):
  if DBG:
    print(x)













class Segtree:
    

    

    
    
    

    

    def __init__(s,l,unit,oper):
        s.unit = unit
        s.oper = oper
        s.n = 1
        while s.n<l:
            s.n *= 2
        s.ary = [s.unit for i in range(2*s.n-1)]

    def get(s,i):
        return s.ary[i+s.n-1]

    def set(s,i,v):
        k = i+s.n-1
        s.ary[k] = v
        while k>0:
            k = (k-1)//2
            s.ary[k] = s.oper( \
                        s.ary[2*k+1], s.ary[2*k+2])

    def setary(s,a):
        for i,v in enumerate(a):
            s.ary[i+s.n-1] = v
        for k in range(s.n-2,-1,-1):
            s.ary[k] = s.oper( \
                        s.ary[2*k+1], s.ary[2*k+2])

    def query(s,x,y):
        l = x+s.n-1
        r = y+s.n-1
        res = s.unit
        while l<r:
            if not l%2:
                res = s.oper(res,s.ary[l])
                l += 1
            if not r%2:
                r -= 1
                res = s.oper(res,s.ary[r])
            l >>= 1
            r >>= 1
        return res





from bisect import bisect_left
n = inn()
xd = []
for i in range(n):
    xx,dd = inm()
    xd.append((xx,dd))
xd.sort()
x = [xd[i][0] for i in range(n)]




r = [i for i in range(n)]
sgt = Segtree(n,0,max)
sgt.setary(r)
f = [0]*(n+1)
f[n] = 1
f[n-1] = 2
for i in range(n-2,-1,-1):
    xx,dd = xd[i]
    j = bisect_left(x,xx+dd)
    k = sgt.query(i,j)
    sgt.set(i,k)
    f[i] = (f[i+1] + f[k+1])%R
    


print(f[0])

Solution (Python):

from sys import setrecursionlimit
setrecursionlimit(10000000)

n = int(input())
xds = [tuple(map(int, input().split())) for _ in range(n)]
xds.sort()

xds.insert(0, (-1000000001, 2000000004))
n += 1

def make_blocks(i):
    x, d = xds[i]
    right = x + d
    res = []
    nexti = i + 1
    while(nexti < n):
        xn, dn = xds[nexti]
        if xn < right:
            l, lasti = make_blocks(nexti)
            res.append(l)
            nexti = lasti + 1
        else:
            return res, nexti - 1
    return res, n - 1

l, _ = make_blocks(0)

def count(l):
    ans = 1
    for ll in l:
        ans = ans * (1 + count(ll)) % 998244353
    return ans

print(count(l))

Solution (Python):
printn = lambda x: print(x,end='')
inn = lambda : int(input())
inl   = lambda: list(map(int, input().split()))
inm   = lambda:      map(int, input().split())
ins = lambda : input().strip()
DBG = True  and False
BIG = 10**18
R = 998244353

def ddprint(x):
  if DBG:
    print(x)


class Segtree:
    

    

    
    
    

    

    def __init__(s,l,unit,oper):
        s.unit = unit
        s.oper = oper
        s.n = 1
        while s.n<l:
            s.n *= 2
        s.ary = [s.unit for i in range(2*s.n-1)]

    def get(s,i):
        return s.ary[i+s.n-1]

    def set(s,i,v):
        k = i+s.n-1
        s.ary[k] = v
        while k>0:
            k = (k-1)//2
            s.ary[k] = max( \
                        s.ary[2*k+1], s.ary[2*k+2])

    def setary(s,a):
        for i,v in enumerate(a):
            s.ary[i+s.n-1] = v
        for k in range(s.n-2,-1,-1):
            s.ary[k] = max( \
                        s.ary[2*k+1], s.ary[2*k+2])

    def query(s,x,y):
        l = x+s.n-1
        r = y+s.n-1
        res = s.unit
        while l<r:
            if not l%2:
                res = s.oper(res,s.ary[l])
                l += 1
            if not r%2:
                r -= 1
                res = s.oper(res,s.ary[r])
            l >>= 1
            r >>= 1
        return res


    def query2(s,x,y):
        return s.querycore(x,y,0,0,s.n)

    
    

    def querycore(s,x,y,k,l,r):
        if r<=x or y<=l:
            return s.unit
        if x<=l and r<=y:
            return s.ary[k]
        vl = s.querycore(x,y,2*k+1,l,(l+r)//2)
        vr = s.querycore(x,y,2*k+2,(l+r)//2,r)
        return max(vl, vr)


from bisect import bisect_left
n = inn()
xd = []
for i in range(n):
    xx,dd = inm()
    xd.append((xx,dd))
xd.sort()
x = [xd[i][0] for i in range(n)]




r = [i for i in range(n)]
sgt = Segtree(n,0,lambda x,y: max(x,y))
sgt.setary(r)
f = [0]*(n+1)
f[n] = 1
f[n-1] = 2
for i in range(n-2,-1,-1):
    xx,dd = xd[i]
    j = bisect_left(x,xx+dd)
    k = sgt.query(i,j)
    sgt.set(i,k)
    f[i] = (f[i+1] + f[k+1])%R
    


print(f[0])

Solution (Python):
import sys
input = sys.stdin.readline

class SegmentTree(object):
 
    def __init__(self, init_array, seg_func=min, seg_func_null=10 ** 9 + 7):
 
        self.seg_func = seg_func
        self.seg_func_null = seg_func_null
        self.n = 1
        while self.n < len(init_array):
            self.n *= 2
        self.dat = [0] * (2 * self.n - 1)
        for i in range(len(init_array)):
            self.dat[self.n - 1 + i] = init_array[i]
        for i in range(self.n - 2, -1, -1):
            self.dat[i] = self.seg_func(self.dat[2 * i + 1], self.dat[2 * i + 2])
 
    def update(self, k, a):
        k += self.n - 1
        self.dat[k] = a
        while k > 0:
            k = (k - 1) // 2
            self.dat[k] = self.seg_func(self.dat[k * 2 + 1], self.dat[k * 2 + 2])
 
    def query(self, p, q):
        
        if q <= p:
            return self.seg_func_null
 
        p += self.n - 1
        q += self.n - 2
        res = self.seg_func_null
 
        while q - p > 1:
            if p & 1 == 0:
                res = self.seg_func(res, self.dat[p])
            if q & 1 == 1:
                res = self.seg_func(res, self.dat[q])
                q -= 1
            p = p // 2
            q = (q-1) // 2
        if p == q:
            res = self.seg_func(res, self.dat[p])
        else:
            res = self.seg_func(self.seg_func(res, self.dat[p]), self.dat[q])
 
        return res






N = int(input())
XD = [None]*N
for i in range(N):
    X, D = (int(i) for i in input().split())
    XD[i] = (X, D)
XD.sort()

seg = SegmentTree(list(range(N)), max, -1)
L = list(range(N))

import bisect
for i in range(N)[::-1]:
    x, d = XD[i]
    b = bisect.bisect_left(XD, (x+d-0.5, d))-1
    m = seg.query(i,b+1)
    seg.update(i,m)
    L[i] = m

ans = [0]*N
res = 1
for i in range(N)[::-1]:
    if L[i] == i:
        ans[i] = res
        res *= 2
    else:
        ans[i] = ans[L[i]]
        res += ans[i]
    res %= 998244353
print(res)