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
def input():
    return sys.stdin.readline()
n = int(input())
xd = [[int(i) for i in input().split()] for _ in range(n)]
xd.sort()


num_max = 2**(n-1).bit_length()
seg_max = [0] * (2 * num_max)
ide_ele_max = -1


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


y = [0] * n
j = n-1
for x, d in reversed(xd):
    if x + d > xd[-1][0]:
        y[j] = n
    else:
        mi = 0
        ma = n - 1
        while mi != ma:
            m = (mi + ma) // 2 + 1
            if xd[m][0] < x + d:
                mi = m
            else:
                ma = m - 1
        if mi == j:
            y[j] = mi+1
        else:
            y[j] = query_max(j+1, mi+1)
    update_max(j, y[j])
    j -= 1
dp = [0] * (n + 1)
dp[-1] = 1
j = n-1
for i in y:
    if j == y[j]:
        dp[j] = dp[j+1]
    dp[j] = (dp[j + 1] + dp[y[j]]) % 998244353
    j -= 1
print(dp[0])

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):
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):
law = 998244353
n = int(input())
robots = [tuple(map(int, input().split())) for _ in range(n)]

robots.sort(reverse = True)

ntrig = [-1] * n
dp = [0] * n
dp[0] = 2
for i, (x, d) in enumerate(robots):
    if i == 0:
        continue
    next = i-1
    while x + d > robots[next][0]:
        next = ntrig[next]
        if next == -1:
            break
    ntrig[i] = next
    if next == -1:
        dp[i] = dp[i-1] + 1
    else:
        dp[i] = dp[i-1] + dp[next]
    dp[i] %= law

print(dp[n-1])

Solution (Python):
n = int(input())
a = sorted((tuple(map(int, input().split())) for i in range(n)))
a.append((10 ** 18, 1))
mo = 998244353
dp = [0] * (n + 1)
dp[n] = 1
f = list(range(n))
fr = list(range(n))
bd = [x + d for x, d in a]
def getF(u):
    if f[f[u]] != f[u]:
        f[u] = getF(f[u])
        return f[u]
    return f[u]
def uniF(u, v):
    u = getF(u)
    v = getF(v)
    if u == v:
        return
    f[u] = v
    fr[v] = max(fr[v], fr[u])
    bd[v] = max(bd[v], bd[u])
for i in range(n - 1, -1, -1):
    cur = i
    while fr[getF(cur)] + 1 < n and a[fr[getF(cur)] + 1][0] < bd[getF(cur)]:
        uniF(cur, fr[getF(cur)] + 1)
    dp[i] = (dp[i + 1] + dp[fr[getF(cur)] + 1]) % mo
print(dp[0])

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

n = int(input())
dg = 10**10
mod = 998244353
xd = []

for i in range(n):
    x,d = map(int,input().split())
    xd.append((x+10**9)*dg + d)

xd.sort()

dp = [0]*(n+1)
ma = list(range(n+1))

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**(n-1).bit_length()
seg_max=[ide_ele_max]*2*num_max

init_max(ma)

dp[n] = 1


for i in range(n-1,-1,-1):
    x,d = xd[i]//dg,xd[i]%dg
    k = bisect.bisect_left(xd,(x+d)*dg)
    
    ma[i] = query_max(i,k)
    update_max(i,ma[i])
    
    dp[i] = (dp[i+1]+dp[ma[i]+1])%mod

print(dp[0]%mod)

Solution (Python):
class segment_tree:
    def __init__(self, N, operator_M, e_M):
        self.op_M = operator_M
        self.e_M = e_M
        
        self.N0 = 1<<(N-1).bit_length()
        self.dat = [self.e_M]*(2*self.N0)
    
    
    def build(self, initial):
        self.dat[self.N0:self.N0+len(initial)] = initial[:]
        for k in range(self.N0-1,0,-1):
            self.dat[k] = self.op_M(self.dat[2*k], self.dat[2*k+1])

    
    def update(self,k,x):
        k += self.N0
        self.dat[k] = x
        k //= 2
        while k:
            self.dat[k] = self.op_M(self.dat[2*k], self.dat[2*k+1])
            k //= 2

    
    def query(self,L,R):
        L += self.N0; R += self.N0 + 1 
        sl = sr = self.e_M
        while L < R:
            if R & 1:
                R -= 1
                sr = self.op_M(self.dat[R],sr)
            if L & 1:
                sl = self.op_M(sl,self.dat[L])
                L += 1
            L >>= 1; R >>= 1
        return self.op_M(sl,sr)

    def get(self, k): 
        return self.dat[k+self.N0]





import sys
sys.setrecursionlimit(10**6)
readline = sys.stdin.readline
read = sys.stdin.read

n = int(input())
xd = [[int(i) for i in readline().split()] for _ in range(n)]
xd.sort(key=lambda x: x[0])

xx = [xdi[0] for xdi in xd]
from bisect import bisect_left

a = [bisect_left(xx,x+d)-1 for x,d in xd]
seg = segment_tree(n, max, 0)
seg.build(a)

b = list(range(n))
for i in range(n-2,-1,-1):
    if i+1 <= a[i]:
        b[i] = seg.query(i+1,a[i])   
        seg.update(i,b[i])

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

MOD = 998244353
for i in range(n-1,-1,-1):
    dp[i] = (dp[i+1] + dp[b[i]+1])%MOD




print(dp[0])

Solution (Python):
import bisect
import sys

stdin = sys.stdin

ni = lambda: int(ns())
na = lambda: list(map(int, stdin.readline().split()))
ns = lambda: stdin.readline().rstrip()  

n = ni()
co = []
for i in range(n):
    co.append(na())
    co[-1][1] += co[-1][0]
co.sort(key=lambda x: x[0])


class Segtreermq:
    def __init__(self, n):
        self.H = 1
        while self.H < n:
            self.H *= 2
        self.M = self.H * 2
        self.vals = [999999999999] * self.M

    def update(self, pos, v):
        self.vals[self.H+pos] = v
        x = self.H+pos>>1
        while x >= 1:
            self.vals[x] = min(self.vals[2*x], self.vals[2*x+1])
            x>>=1

    def min(self, l, r):
        ret = 999999999999999
        if l >= r:
            return ret
        while l != 0:
            f = l&-l
            if l+f > r:
                break
            v = self.vals[(self.H+l)//f]
            if v < ret:
                ret = v
            l += f

        while l < r:
            f = r & -r
            v = self.vals[(self.H+r)//f-1]
            if v < ret:
                ret = v
            r -= f
        return ret

xs = [_[0] for _ in co]

st = Segtreermq(n)
for i in range(n-1,-1,-1):
    ind = bisect.bisect_left(xs, co[i][1])
    reach = max(co[i][1], -st.min(i, ind))
    st.update(i, -reach)
    co[i][1] = reach

mod = 998244353
stack = []
dp = [0] * n
for i in range(n-1,-1,-1):
    val = 1
    while len(stack) > 0 and co[stack[-1]][1] <= co[i][1]:
        val = val * dp[stack[-1]] % mod
        stack.pop(-1)
    dp[i] = (val + 1) % mod
    stack.append(i)

ans = 1
for s in stack:
    ans = ans * dp[s] % mod
print(ans)

Solution (Python):
import sys
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
readlines = sys.stdin.buffer.readlines
from bisect import bisect_left

MOD = 998244353

N = int(readline())
m = map(int,read().split())
XD = sorted(zip(m,m))
X, D = zip(*XD)

class MaxSegTree():
    def __init__(self,raw_data):
        N = len(raw_data)
        self.size = 1<<(N.bit_length()) 
        self.data = [0] * (2*self.size)
        self.build(raw_data)
        
    def build(self,raw_data):
        
        for i,x in enumerate(raw_data):
            self.data[self.size+i] = x
        for i in range(self.size-1,0,-1):
            x = self.data[i+i]; y = self.data[i+i+1]
            self.data[i] = x if x>y else y
    
    def update(self,i,x):
        i += self.size
        self.data[i] = x
        i >>= 1
        while i:
            x = self.data[i+i]; y = self.data[i+i+1]
            self.data[i] = x if x>y else y
            i >>= 1
    
    def get_data(self,i):
        return self.data[i+self.size]

    def get_max(self,L,R):
        
        L += self.size
        R += self.size + 1
        
        x = 0
        while L < R:
            if L&1:
                y = self.data[L]
                if x < y: x = y
                L += 1
                
            if R&1:
                R -= 1
                y = self.data[R]
                if x < y: x = y
            L >>= 1; R >>= 1
        return x

R = [0] + [bisect_left(X, x + d) for x,d in XD]
seg = MaxSegTree(R)

S = [0] * len(R)
for n in range(N,0,-1):
    r = R[n]
    x = seg.get_max(n, r)
    S[n] = x
    seg.update(n, x)    

dp = [0] * (N+1)
dp[0] = 1
dp_cum = [1] * (N+1)
for n,r in enumerate(S[1:],1):
    dp[r] += dp_cum[n-1]
    dp[r] %= MOD
    dp_cum[n] = dp_cum[n-1] + dp[n]
    dp_cum[n] %= MOD

print(dp_cum[-1])