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.



Sample input:
2
1 5
3 3


Sample output:
3

Submission status: Accepted

Solution code:
def main():
    n = int(input())
    xd = [map(int, input().split()) for _ in range(n)]
    mod = 998244353
    INF = 10 ** 10

    xx = [(x, x + d, i) for i, (x, d) in enumerate(xd, 1)]
    xx.sort()
    adj = [[] for _ in range(n + 1)]
    stack = [(INF, 0)]
    for l, r, i in xx:
        while stack[-1][0] <= l:
            stack.pop()

        ip = stack[-1][1]
        adj[ip].append(i)
        stack.append((r, i))

    stack2 = [0]
    d = [-1] * (n + 1)
    d[0] = 0
    c = [[] for _ in range(n + 1)]
    order = []
    while stack2:
        u = stack2.pop()
        order.append(u)
        for v in adj[u]:
            if d[v] == -1:
                d[v] = d[u] + 1
                c[u].append(v)
                stack2.append(v)

    dp = [1] * (n + 1)
    for u in order[::-1]:
        for v in c[u]:
            dp[u] *= dp[v]
            dp[u] %= mod

        dp[u] += 1
        dp[u] %= mod

    ans = dp[0] - 1
    ans %= mod
    print(ans)


if __name__ == "__main__":
    main()

Submission status: Accepted

Solution code:
#!/usr/bin/python3

M = 998244353

n = int(input())
r = []
for i in range(n):
    (x, d) = map(int, input().split())
    r.append((x, x + d))

r.sort()
cls = []
dp = [0 for i in range(n + 1)]
dp[n] = 1
for i in range(n - 1, -1, -1):
    ne = i + 1
    #merge cluster
    while cls:
        (ci, cne) = cls[-1]
        if r[ci][0] < r[i][1]:
            cls.pop()
            ne = cne
        else:
            break;
    cls.append((i, ne))
        
    dp[i] = (dp[i + 1] + dp[ne]) % M

print(dp[0])

Submission status: Accepted

Solution code:
#!/usr/bin/python3

M = 998244353

n = int(input())
r = []
for i in range(n):
    (x, d) = map(int, input().split())
    r.append((x, x + d))

r.sort()
cls = []
dp = {}
dp[n] = 1
for i in range(n - 1, -1, -1):
    ne = i + 1
    #make cluster
    while cls:
        (ci, cne) = cls[-1]
        if r[ci][0] < r[i][1]:
            cls.pop()
            ne = cne
        else:
            break;
    cls.append((i, ne))
        
    dp[i] = (dp[i + 1] + dp[ne]) % M

print(dp[0])

Submission status: Accepted

Solution code:
import sys
readline = sys.stdin.readline
MOD = 998244353

class Segtree:
    def __init__(self, A, intv, initialize = True, segf = max):
        self.N = len(A)
        self.N0 = 2**(self.N-1).bit_length()
        self.intv = intv
        self.segf = segf
        if initialize:
            self.data = [intv]*self.N0 + A + [intv]*(self.N0 - self.N)
            for i in range(self.N0-1, 0, -1):
                self.data[i] = self.segf(self.data[2*i], self.data[2*i+1]) 
        else:
            self.data = [intv]*(2*self.N0)
        
    def update(self, k, x):
        k += self.N0
        self.data[k] = x
        while k > 0 :
            k = k >> 1
            self.data[k] = self.segf(self.data[2*k], self.data[2*k+1])
    
    def query(self, l, r):
        L, R = l+self.N0, r+self.N0
        s = self.intv
        while L < R:
            if R & 1:
                R -= 1
                s = self.segf(s, self.data[R])
            if L & 1:
                s = self.segf(s, self.data[L])
                L += 1
            L >>= 1
            R >>= 1
        return s
    
    def binsearch(self, l, r, check, reverse = False):
        L, R = l+self.N0, r+self.N0
        SL, SR = [], []
        while L < R:
            if R & 1:
                R -= 1
                SR.append(R)
            if L & 1:
                SL.append(L)
                L += 1
            L >>= 1
            R >>= 1
        
        if reverse:
            for idx in (SR + SL[::-1]):
                if check(self.data[idx]):
                    break
            else:
                return -1
            while idx < self.N0:
                if check(self.data[2*idx+1]):
                    idx = 2*idx + 1
                else:
                    idx = 2*idx
            return idx - self.N0
        else:
            for idx in (SL + SR[::-1]):
                if check(self.data[idx]):
                    break
            else:
                return -1
            while idx < self.N0:
                if check(self.data[2*idx]):
                    idx = 2*idx
                else:
                    idx = 2*idx + 1
            return idx - self.N0

N = int(readline())
XD = [tuple(map(int, readline().split())) for _ in range(N)]
XD.sort(key = lambda x: (x[0], -x[1]))

sXD = []
seen = set()
for x, d in XD:
    if x not in seen:
        sXD.append((x, d))
        seen.add(x)

N = len(sXD)
table = list(range(N))
T = Segtree(table, -1, initialize = True, segf = max)
X, D = map(list, zip(*sXD))
for i in range(N-1, -1, -1):
    ok = i
    ng = N
    gi = X[i] + D[i]
    while abs(ok-ng) > 1:
        med = (ok+ng)//2
        if X[med] < gi:
            ok = med
        else:
            ng = med
    table[i] = T.query(i, ok+1)
    T.update(i, table[i])

dp = [0]*(N+1)
dp[N] = 1
Dp = dp[:]
for i in range(N-1, -1, -1):
    dp[i] = Dp[table[i]+1]
    Dp[i] = (Dp[i+1] + dp[i])%MOD
print(Dp[0])

Submission status: Accepted

Solution code:
from collections import defaultdict, deque, Counter
from heapq import heappush, heappop, heapify
from bisect import bisect_right, bisect_left
import random
from itertools import permutations, accumulate, combinations, product
import sys
import string
from bisect import bisect_left, bisect_right
from math import factorial, ceil, floor, gamma, log
from operator import mul
from functools import reduce
from copy import deepcopy

sys.setrecursionlimit(2147483647)
INF = 10 ** 20
def LI(): return list(map(int, sys.stdin.buffer.readline().split()))
def I(): return int(sys.stdin.buffer.readline())
def LS(): return sys.stdin.buffer.readline().rstrip().decode('utf-8').split()
def S(): return sys.stdin.buffer.readline().rstrip().decode('utf-8')
def IR(n): return [I() for i in range(n)]
def LIR(n): return [LI() for i in range(n)]
def SR(n): return [S() for i in range(n)]
def LSR(n): return [LS() for i in range(n)]
def SRL(n): return [list(S()) for i in range(n)]
def MSRL(n): return [[int(j) for j in list(S())] for i in range(n)]
mod = 998244353

class Segtree:
    def __init__(self, A, ide_ele, segfunc, initialize=True):
        self.n = len(A)
        self.size = 2 ** (self.n - 1).bit_length()
        self.ide_ele = ide_ele
        self.segfunc = segfunc
        if initialize:
            self.data = [ide_ele] * self.size + A + [ide_ele] * (self.size - self.n)
            for i in range(self.size - 1, 0, -1):
                self.data[i] = self.segfunc(self.data[2 * i], self.data[2 * i + 1])
        else:
            self.data = [ide_ele] * (2 * self.size)

    def update(self, k, x):
        k += self.size
        self.data[k] = x
        while k:
            k = k >> 1
            self.data[k] = self.segfunc(self.data[2 * k], self.data[2 * k + 1])

    def query(self, l, r):
        L, R = l + self.size, r + self.size
        s = self.ide_ele
        while L < R:
            if R & 1:
                R -= 1
                s = self.segfunc(s, self.data[R])
            if L & 1:
                s = self.segfunc(s, self.data[L])
                L += 1
            L >>= 1
            R >>= 1
        return s


n = I()
XD = sorted(LIR(n))
X = []
D = []
for x, d in XD:
    X += [x]
    D += [d]

last = [l for l in range(n)]
st = Segtree(last, -INF, max)
for i in range(n - 2, -1, -1):
    r = bisect_left(X, X[i] + D[i])
    ret = st.query(i, r)
    st.update(i, ret)
    last[i] = ret

dp = [1] * (n + 1)
for j in range(n - 1, -1, -1):
    k = last[j]
    dp[j] = (dp[j + 1] + dp[k + 1]) % mod


print(dp[0])

Submission status: Accepted

Solution code:
from collections import defaultdict, deque, Counter
from heapq import heappush, heappop, heapify
from bisect import bisect_right, bisect_left
import random
from itertools import permutations, accumulate, combinations, product
import sys
import string
from bisect import bisect_left, bisect_right
from math import factorial, ceil, floor, gamma, log
from operator import mul
from functools import reduce
from copy import deepcopy

sys.setrecursionlimit(2147483647)
INF = 10 ** 20
def LI(): return list(map(int, sys.stdin.buffer.readline().split()))
def I(): return int(sys.stdin.buffer.readline())
def LS(): return sys.stdin.buffer.readline().rstrip().decode('utf-8').split()
def S(): return sys.stdin.buffer.readline().rstrip().decode('utf-8')
def IR(n): return [I() for i in range(n)]
def LIR(n): return [LI() for i in range(n)]
def SR(n): return [S() for i in range(n)]
def LSR(n): return [LS() for i in range(n)]
def SRL(n): return [list(S()) for i in range(n)]
def MSRL(n): return [[int(j) for j in list(S())] for i in range(n)]
mod = 998244353

class Segtree:
    def __init__(self, A, ide_ele, segfunc, initialize=True):
        self.n = len(A)
        self.size = 2 ** (self.n - 1).bit_length()
        self.ide_ele = ide_ele
        self.segfunc = segfunc
        if initialize:
            self.data = [ide_ele] * self.size + A + [ide_ele] * (self.size - self.n)
            for i in range(self.size - 1, 0, -1):
                self.data[i] = self.segfunc(self.data[2 * i], self.data[2 * i + 1])
        else:
            self.data = [ide_ele] * (2 * self.size)

    def update(self, k, x):
        k += self.size
        self.data[k] = x
        while k > 0:
            k = k >> 1
            self.data[k] = self.segfunc(self.data[2 * k], self.data[2 * k + 1])

    def query(self, l, r):
        L, R = l + self.size, r + self.size
        s = self.ide_ele
        while L < R:
            if R & 1:
                R -= 1
                s = self.segfunc(s, self.data[R])
            if L & 1:
                s = self.segfunc(s, self.data[L])
                L += 1
            L >>= 1
            R >>= 1
        return s


n = I()
XD = sorted(LIR(n))
X = []
D = []
for x, d in XD:
    X += [x]
    D += [d]

last = [l for l in range(n)]
st = Segtree(last, -INF, max)
for i in range(n - 2, -1, -1):
    r = bisect_left(X, X[i] + D[i])
    ret = st.query(i, r)
    st.update(i, ret)
    last[i] = ret

dp = [1] * (n + 1)
for j in range(n - 1, -1, -1):
    k = last[j]
    dp[j] = (dp[j + 1] + dp[k + 1]) % mod


print(dp[0])

Submission status: Accepted

Solution code:
n = int(input()); arr = [list(map(int,input().split())) for _ in range(n)]

mod = 998244353
ans = 0
arr.sort(key=lambda x: x[0],reverse=True)
pos = [i[0] for i in arr]
moved = [sum(i) for i in arr]
children = [i for i in range(-1,n)]

for i in range(1,n):
    parent = moved[i]
    child = children[i]
    cmp = pos[child]
    while cmp < parent:
        child = children[child]
        if child == -1:
            break
        cmp = pos[child]
    children[i] = child
    
dp = [0] * (n+1)
dp[n] = 1
for i in range(n):
    dp[i] = dp[i-1] + dp[children[i]]
    dp[i] %= mod
    
print(dp[n-1])

Submission status: Accepted

Solution code:
def main():
    mod = 998244353
    n = int(input())
    ab = sorted([tuple(map(int, input().split())) for _ in [0]*n])
    next_idx = [-1]*n
    for i in range(n-1, -1, -1):
        dist = sum(ab[i])
        now = i
        while now < n-1:
            a1, b1 = ab[now+1]
            if a1 < dist:
                now = next_idx[now+1]
            else:
                break
        next_idx[i] = now
    dp = [0]*(n+1)
    dp[n] = 1
    for i in range(n-1, -1, -1):
        dp[i] = (dp[i+1]+dp[next_idx[i]+1]) % mod
    print(dp[0])


main()

Submission status: Accepted

Solution code:
def main():
    mod = 998244353
    n = int(input())
    ab = [tuple(map(int, input().split())) for _ in [0]*n]
    ab.sort()
    next_a = [-1]*n
    dp = [0]*(n+1)
    dp[n] = 1
    for i in range(n-1, -1, -1):
        a0, b0 = ab[i]
        dist = a0+b0
        now = i
        while now < n-1:
            a1, b1 = ab[now+1]
            if a1 < dist:
                now = next_a[now+1]
            else:
                break
        next_a[i] = now
    for i in range(n-1, -1, -1):
        dp[i] = (dp[i+1]+dp[next_a[i]+1]) % mod
    print(dp[0] % mod)


main()

Submission status: Accepted

Solution code:
mod = 998244353
from bisect import bisect_left
from operator import itemgetter
N = int(input())
xd = [list(map(int,input().split())) for _ in range(N)]
xd.sort(key=itemgetter(0))
X = [xd[i][0] for i in range(N)]
D = [xd[i][1] for i in range(N)]

N0 = 2**(N-1).bit_length()
INF = 2**31-1
data = [INF]*(4*N0) #長さが足りないことがある. 3*N0にすればいい?

# k番目の要素をxに更新
def update(k, x):
    k += N0-1
    data[k] = x
    while k >= 0:
        k = (k - 1) // 2
        data[k] = min(data[2*k+1], data[2*k+2])

# [l,r)の最小値
def query(l, r):
    L = l + N0; R = r + N0
    s = INF
    while L < R:
        if R & 1:
            R -= 1
            s = min(s, data[R-1])

        if L & 1:
            s = min(s, data[L-1])
            L += 1
        L >>= 1; R >>= 1
    return s

for i in range(N-1,-1,-1):
    j = bisect_left(X,X[i]+D[i])
    update(i,-i)
    update(i,query(i,j))

dp = [0]*(N+1)
dp[-1] = 1
for i in range(N-1,-1,-1):
    dp[i] += dp[i+1]
    dp[i] += dp[-query(i,i+1)+1]
    dp[i] %= mod

print(dp[0])

Submission status: Accepted

Solution code:
INF = 10**18
MOD = 998244353

N = int(input())
robots = [(-INF, INF)]

for _ in range(N):
    x, d = map(int, input().split())
    robots.append((x, x + d))

robots.sort()
stack = list()

tree = [[] for _ in range(N + 1)]

for i in range(N + 1)[::-1]:
    x, r = robots[i]
    while stack and stack[-1][0] < r:
        y, j = stack.pop()
        tree[i].append(j)
    stack.append((x, i))

stack = list()
stack.append(0)

visited = [0 for _ in range(N + 1)]
visited[0] = 1
order = [None for _ in range(N + 1)]
order[0] = 0
od = 0

while stack:
    node = stack.pop()
    for adj in tree[node]:
        if not visited[adj]:
            visited[adj] = 1
            od += 1
            order[od] = adj
            stack.append(adj)

dp = [1 for _ in range(N + 1)]

for node in order[::-1]:
    for adj in tree[node]:
        dp[node] *= dp[adj]
    dp[node] += 1
    dp[node] %= MOD

print(dp[0] - 1)

Submission status: Accepted

Solution code:
import bisect
n=int(input())
x=[]
d=[]
mod=998244353
l=[]
for i in range(n):
    l.append(list(map(int,input().split())))
l.sort(key=lambda x:x[0])
for i in range(n):
    a,b=l[i][0],l[i][1]
    x.append(a)
    d.append(b)

r=[0]*n
r[-1]=n-1
for i in range(n-2,-1,-1):
    xi=bisect.bisect_left(x,x[i]+d[i])
    xi-=1
    r[i]=xi
    #if xi==i:
        #r[i]=i
    #else:
        #r[i]=r[xi]

#####segfunc######                                                              
def segfunc(x,y):
    return max(x,y)

def init(init_val):
    #set_val                                                                    
    for i in range(n):
        seg[i+num-1]=init_val[i]
    #built                                                                      
    for i in range(num-2,-1,-1):
        seg[i]=segfunc(seg[2*i+1],seg[2*i+2])
    
def update(k,x):
    k+=num-1
    seg[k]=x
    while k+1:
        k=(k-1)//2
        seg[k]=segfunc(seg[k*2+1],seg[k*2+2])

def query(p,q):
    if q<=p:
        return ide_ele
    p+=num-1
    q+=num-2
    res=ide_ele
    while q-p>1:
        if p&1==0:
            res=segfunc(res,seg[p])
        if q&1==1:
            res=segfunc(res,seg[q])
            q-=1
        p=p//2
        q=(q-1)//2
    if p==q:
        res=segfunc(res,seg[p])
    else:
        res=segfunc(segfunc(res,seg[p]),seg[q])
    return res

ide_ele=-10
num=2**(n-1).bit_length()
seg=[ide_ele]*2*num
init(r)
rr=[0]*n
rr[-1]=n-1
for i in range(n-2,-1,-1):
    rr[i]=query(i,r[i]+1)
    update(i,rr[i])

dp=[0]*(n+1)
dp[-2]=2
dp[-1]=1
for i in range(n-2,-1,-1):    
    dp[i]=(dp[i+1]+dp[rr[i]+1])%mod
print((dp[0])%mod)

Submission status: Accepted

Solution code:
import sys
input = lambda : sys.stdin.readline().rstrip()

M = 998244353

n = int(input())
xs = [0] * n
ds = [0] * n
for i in range(n):
    x, d = (int(c) for c in input().split())
    ds[i] = d
    xs[i] = (x,i)

import sys
sys.setrecursionlimit(max(1000,n))

xs.sort()
index = [x[1] for x in xs]
xs = [x[0] for x in xs]
ds = [ds[ind] for ind in index]

def _sub(i):
    # 深さ優先探索しながらi番目以下の組み合わせと、次に調べるべき番号を返す
    if i==n-1:
        return 2, n
    res = 1
    ind = i+1
    while True:
        if (xs[i]+ds[i] <= xs[ind]):
            break
        o, ind = _sub(ind)
        res *= o
        res %= M
        if ind>=n:
            break
    return res+1, ind
out = []
done = 0
while True:
    o, done = _sub(done)
    out.append(o)
    if done>=n:
        break
result = 1
for o in out:
    result *= o
    result %= M
print(result)

Submission status: Accepted

Solution code:

import numpy as np

M = 998244353

n = int(input())
xs = [0] * n
ds = [0] * n
for i in range(n):
    x, d = (int(c) for c in input().split())
    ds[i] = d
    xs[i] = x
xs = np.array(xs)
ds = np.array(ds)

import sys
sys.setrecursionlimit(max(1000,n))

index = xs.argsort()
xs = xs[index]
ds = ds[index]

def _sub(i):
    # 深さ優先探索しながらi番目以下の組み合わせと、次に調べるべき番号を返す
    if i==n-1:
        return 2, n
    res = 1
    ind = i+1
    while True:
        if (xs[i]+ds[i] <= xs[ind]):
            break
        o, ind = _sub(ind)
        res *= o
        res %= M
        if ind>=n:
            break
    return res+1, ind
out = []
done = 0
while True:
    o, done = _sub(done)
    out.append(o)
    if done>=n:
        break
result = 1
for o in out:
    result *= o
    result %= M
print(result)

Submission status: Accepted

Solution code:
#!/usr/bin/env python3
from collections import defaultdict,deque
from heapq import heappush, heappop
from bisect import bisect_left, bisect_right
import sys, random, itertools, math
sys.setrecursionlimit(10**5)
input = sys.stdin.readline
sqrt = math.sqrt
def LI(): return list(map(int, input().split()))
def LF(): return list(map(float, input().split()))
def LI_(): return list(map(lambda x: int(x)-1, input().split()))
def II(): return int(input())
def IF(): return float(input())
def LS(): return list(map(list, input().split()))
def S(): return list(input().rstrip())
def IR(n): return [II() for _ in range(n)]
def LIR(n): return [LI() for _ in range(n)]
def FR(n): return [IF() for _ in range(n)]
def LFR(n): return [LI() for _ in range(n)]
def LIR_(n): return [LI_() for _ in range(n)]
def SR(n): return [S() for _ in range(n)]
def LSR(n): return [LS() for _ in range(n)]


mod = 998244353

inf = 1e10


#solve
def solve():


    def init_max(init_max_val):
        #set_val
        for i in range(n):
            seg_max[i+num_max-1] = init_max_val[i]
        #built
        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

    n = II()
    #####単位元######
    ide_ele_max = -1

    #num_max:n以上の最小の2のべき乗
    num_max = 2**(n).bit_length()
    seg_max = [ide_ele_max]*2*num_max
    xd = LIR(n)
    xd.sort()
    x = [x for x, d in xd]
    dp = [[0] * 2 for i in range(n + 1)]
    On = 0
    Off = 1
    dp[-1][On] =  1
    for i in range(n - 1, -1, -1):
        dp[i][Off] = (dp[i + 1][On] + dp[i + 1][Off]) % mod
        j = bisect_right(x, x[i] + xd[i][1] - 1) - 1
        if j == i:
            dp[i][On] = (dp[i + 1][On] + dp[i + 1][Off]) % mod
            update_max(i, i)
        else:
            j = query_max(i, j + 1)
            dp[i][On] = dp[j][On]
            update_max(i, j)
        
    print(sum(dp[0]) % mod)
    return


#main
if __name__ == '__main__':
    solve()

Submission status: Accepted

Solution code:
import bisect
import sys
input = sys.stdin.readline


class SegmentTreeRMQ(object):  # 1-indexed
    def __init__(self, size, value):
        self.len = 1 << size.bit_length()
        # print(self.len)
        self.array = [value] * (2 * self.len)

    def update(self, i, x):
        i += self.len
        while i > 0:
            self.array[i] = max(self.array[i], x)
            i >>= 1
        # print(self.array)

    def get(self, i):
        return self.array[i + self.len]

    def get_maximum(self, l, r):
        L = l+self.len
        R = r+self.len
        ANS = -1 << 30

        while L < R:
            if L & 1:
                ANS = max(ANS, self.array[L])
                L += 1

            if R & 1:
                R -= 1
                ANS = max(ANS, self.array[R])
            L >>= 1
            R >>= 1

        return ANS


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

xd_array = sorted(xd_array, key=lambda x: x[0])
x_array = [i[0] for i in xd_array]
d_array = [i[1] for i in xd_array]

mod = 998244353

tree = SegmentTreeRMQ(N, -1)
ans_array = [0] * (N+1)
ans_array[-1] = 1
for i in range(N-1, -1, -1):
    move = x_array[i] + d_array[i] - 0.1
    max_index = bisect.bisect_left(x_array, move)
    max_move = max(i, tree.get_maximum(i, max_index))
    tree.update(i, max_move)
    ans_array[i] = (ans_array[i+1] + ans_array[max_move + 1]) % mod

print(ans_array[0])

Submission status: Accepted

Solution code:
import sys
import math
from collections import defaultdict
from bisect import bisect_left, bisect_right

sys.setrecursionlimit(10**7)
def input():
    return sys.stdin.readline()[:-1]

mod = 998244353

def I(): return int(input())
def LI(): return list(map(int, input().split()))
def LIR(row,col):
    if row <= 0:
        return [[] for _ in range(col)]
    elif col == 1:
        return [I() for _ in range(row)]
    else:
        read_all = [LI() for _ in range(row)]
        return map(list, zip(*read_all))

#################

from operator import itemgetter

def index_sort(A):
    A_sort = sorted(enumerate(A),key=itemgetter(1))
    index = [a[0] for a in A_sort]
    sorted_A = [a[1] for a in A_sort]
    return index, sorted_A

# 一点更新セグメントツリー
## 更新：１点の値をxに更新する　　クエリ演算：op
## 0-indexed
class SegmentTree:
    def __init__(self,N,default):
        # 演算の定義
        self.op = max
        # 初期化の値
        self.default = default
        self.N0 = 2**(N-1).bit_length()
        self.tree = [self.default]*(2*self.N0)
        
    # k番目の値をxに更新
    def update(self,k,x):
        k += self.N0-1
        self.tree[k] = x
        while k >= 0:
            k = (k-1)//2
            self.tree[k] = self.op(self.tree[2*k+1], self.tree[2*k+2])

    # 区間[l,r]へのクエリ
    def query(self,l,r):
        L = l+self.N0
        R = r+self.N0+1 
        s = self.default
        while L < R:
            if R & 1:
                R -= 1
                s = self.op(s,self.tree[R-1])
            if L & 1:
                s = self.op(s,self.tree[L-1])
                L += 1
            L >>= 1; R >>= 1
        return s

    # k番目の値を取得
    def get(self,k):
        return self.tree[k+self.N0-1]

N = I()
X,D = LIR(N,2)

index,X = index_sort(X)
D = [D[i] for i in index]

# iを選んだときに除かれる右端
end = SegmentTree(N,0)
for i in range(N):
    end.update(i,i)
for i in range(N-1)[::-1]:
    p = bisect_right(X,X[i]+D[i]-1)
    val = end.query(i,p-1)
    end.update(i,val)

# i以降を自由に使って作れる場合の数
dp = [0]*N
dp[N-1] = 2
for i in range(N-1)[::-1]:
    dp[i] = dp[i+1]
    if end.get(i) == N-1:
        dp[i] += 1
    else:
        dp[i] += dp[end.get(i)+1]
    dp[i] %= mod

print(dp[0])

Submission status: Accepted

Solution code:
N=int(input());R,d,f,s,x=sorted(list(map(int,input().split()))for i in range(N))+[(2e9,0)],[0]*N+[1],[0]*N,1,N
for i in range(N-1,-1,-1):
	while R[x][0]<sum(R[i]):x=f[x]
	d[i]=s=(s+d[x])%998244353;f[i],x=x,i
print(s)

Submission status: Accepted

Solution code:
N=int(input());R,d,f,s,x=sorted(list(map(int,input().split()))for i in range(N))+[(2e9,0)],[0]*N+[1],[0]*N,1,N
for i in range(N-1,-1,-1):
	while R[x][0]<sum(R[i]):x=f[x]
	d[i]=s=(s+d[x])%998244353;f[i],x=x,i
print(d[0])

Submission status: Accepted

Solution code:
N=int(input())
R,d,f,s,x=sorted(list(map(int,input().split()))for i in range(N))+[(2e9,0)],[0]*N+[1],[0]*N,1,N
for i in range(N-1,-1,-1):
	while R[x][0]<sum(R[i]):x=f[x]
	d[i]=s=(s+d[x])%998244353;f[i],x=x,i
print(d[0])

Submission status: Accepted

Solution code:
N=int(input())
R,d,f,s=sorted(list(map(int,input().split()))for i in range(N))+[(2e9,0)],[0]*N+[1],[0]*N,1
for i in range(N-1,-1,-1):
    x=i+1
    while x<N and R[x][0]<sum(R[i]):x=f[x]
    f[i]=x
    d[i]=s=(s+d[x])%998244353
print(d[0])

Submission status: Accepted

Solution code:
def i1():
 return int(input())
def i2():
 return [int(i) for i in input().split()]
import bisect
mod=998244353
n=int(input())
d=[]
N=1<<(n.bit_length())
t=[-1 for i in range(2*N-1)]

def ud(i,x):
  i+=N-1
  t[i]=x
  while i:
    i=(i-1)>>1
    if t[i*2+1]>t[i*2+2]:t[i]=t[i*2+1]
    else:t[i]=t[i*2+2]
     

def qr(a,b):
    a+=N-1
    b+=N-1
    L = -1
    R = -1
    while a < b:
      if a&1==0:
         if L<t[a]:L = t[a]
      if b&1==0:
         b-=1
         if R<t[b]:R = t[b]
      
      a>>=1
      b>>=1
      
         
    return max(L, R)
 
for i in range(n):
  d.append([int(i) for i in input().split()])
d.sort()
dx=[]
dd=[]
for i,j in d:
  dx.append(i)
  dd.append(j)
for i in range(n)[::-1]:
 tx=dx[i]+dd[i]
 j=bisect.bisect_left(dx,tx)
 tt=qr(i,j)
 if j-1>tt:ud(i,j-1)
 else:ud(i,tt)
dp=[0 for i in range(n+1)]
dp[-1]=1
for i in range(n)[::-1]:
  dp[i]+=dp[i+1]
  dp[i]%=mod
  dp[i]+=dp[t[i+N-1]+1]
  dp[i]%=mod
print(dp[0])

Submission status: Accepted

Solution code:
import sys
reader = (s.rstrip() for s in sys.stdin)
input = reader.__next__

class RangeMinimumQuery:
    def __init__(self, n, F=min, e=float("inf"), fill=None):
        self.n0 = 2**(n-1).bit_length()
        self.F = F
        self.e = e
        if fill is None:
            fill = e
        self.data = [fill]*(2*self.n0)

    def construct(self, a):
        for i, x in enumerate(a):
            self.data[i+self.n0-1] = x
        for i in range(self.n0-2, -1, -1):
            self.data[i] = self.F(self.data[2*i+1], self.data[2*i+2])

    def query(self, l,r):
        l += self.n0
        r += self.n0
        res = self.e
        while l < r:
            if r&1:
                r -= 1
                res = self.F(res, self.data[r-1])
            if l&1:
                res = self.F(res, self.data[l-1])
                l += 1
            l >>=1
            r >>=1
        return res

    def update(self, i, x):
        i += self.n0-1
        self.data[i] = x
        while i:
            i = ~-i//2
            self.data[i] = self.F(self.data[2*i+1], self.data[2*i+2])


from bisect import bisect_left

mod = 998244353

n = int(input())
xd = [list(map(int, input().split())) for i in range(n)]
xd.sort()
xs = [i for i,j in xd]

RMQ = RangeMinimumQuery(n, max,0,0)
RMQ.construct(list(range(n)))

for i in reversed(range(n)):
    r = sum(xd[i])
    j = bisect_left(xs, r)
    k = RMQ.query(i, j)
    RMQ.update(i, k)

DP = [0]*(n+1)
DP[-1] = 1
for i in reversed(range(n)):
    j = RMQ.query(i, i+1)
    DP[i] = DP[i+1]+DP[j+1]
    DP[i] %= mod
print(DP[0])

Submission status: Accepted

Solution code:
class SegmentTreeMax():
  def __init__(self,n,init):
    self.offset=2**((n-1).bit_length())
    self.tree=[init]*(2*self.offset)
    self.init=init
  def update(self,pos,val):
    pos+=self.offset
    self.tree[pos]=val
    while pos>1:
      pos=pos//2
      self.tree[pos]=max(self.tree[2*pos],self.tree[2*pos+1])
  def query(self,l,r):
    l+=self.offset
    r+=self.offset
    ret=self.init
    while l<=r:
      ret=max(ret,self.tree[r])
      r=(r-1)//2
      ret=max(ret,self.tree[l])
      l=(l+1)//2
    return ret

mod=998244353
n=int(input())
arr=[list(map(int,input().split())) for _ in range(n)]
arr=sorted(arr,key=lambda x:x[0])
st=SegmentTreeMax(n,0)
ranges=[]
for i in range(n):
  x=arr[i][0]+arr[i][1]
  l=-1
  r=n
  while r-l!=1:
    mid=(l+r)//2
    if arr[mid][0]>=x:
      r=mid
    else:
      l=mid
  ranges.append(r-1)
  st.update(i,r-1)
for i in range(n-1,-1,-1):
  ranges[i]=st.query(i,ranges[i])
  st.update(i,ranges[i])
dp=[0]*(n+1)
dp[-1]=1
for i in range(n-1,-1,-1):
  j=ranges[i]+1
  dp[i]=dp[i+1]+dp[j]
  dp[i]%=mod
print(dp[0])