Problem:


Score : 400 points

Problem Statement

You are given a sequence A_1, A_2, ..., A_N and an integer K.

Print the maximum possible length of a sequence B that satisfies the following conditions:

B is a (not necessarily continuous) subsequence of A.

For each pair of adjacents elements of B, the absolute difference of the elements is at most K.

Constraints

1 \leq N \leq 300,000

0 \leq A_i \leq 300,000

0 \leq K \leq 300,000

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N K
A_1
A_2
:
A_N

Output

Print the answer.

Sample Input 1

10 3
1
5
4
3
8
6
9
7
2
4

Sample Output 1

7

For example, B = (1, 4, 3, 6, 9, 7, 4) satisfies the conditions.

It is a subsequence of A = (1, 5, 4, 3, 8, 6, 9, 7, 2, 4).

All of the absolute differences between two adjacent elements (|1-4|, |4-3|, |3-6|, |6-9|, |9-7|, |7-4|) are at most K = 3.



Sample input:
10 3
1
5
4
3
8
6
9
7
2
4


Sample output:
7

Submission status: Accepted

Solution code:
from functools import reduce
from fractions import gcd
import math
import bisect
import itertools
import sys
sys.setrecursionlimit(10000000)
input = sys.stdin.readline
INF = float("inf")


# update: node[x] を更新する
# getmin: 区間 [a, b) の最小値を返す
class SegmentTree:
    def __init__(self, arr):
        size = len(arr)
        n = 1 << size.bit_length()
        self.n = n
        self.node = [0]*(2*n - 1)
        for i in range(size):
            self.node[i+n-1] = arr[i]
        for i in reversed(range(n-2)):
            self.node[i] = max(self.node[2*i+1], self.node[2*i+2])
    
    def update(self, x, val):
        x += (self.n - 1)
        self.node[x] = val
        while x > 0:
            x = (x - 1) // 2
            self.node[x] = max(self.node[2*x+1], self.node[2*x+2])
    
    def getmax(self, l, r):
        res = 0
        l += self.n - 1
        r += self.n - 1
        while l <= r:
            res = max(res, self.node[l])
            res = max(res, self.node[r])
            l  = l // 2
            r = r // 2 - 1
        return res
 

# 処理内容
def main():
    N, K = map(int, input().split())
    
    seg = SegmentTree([0]*300010)
    ans = 0
    for _ in range(N):
        A = int(input())
        a = max(A-K, 0)
        b = min(A+K, 300000)
        tmp = seg.getmax(a, b) + 1
        ans = max(ans, tmp)
        seg.update(A, tmp)
    
    print(ans)


if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
from collections import defaultdict,deque
import sys,heapq,bisect,math,itertools,string,queue,datetime
def inpl(): return list(map(int, input().split()))
def inpl_s(): return list(input().split())

N,K = inpl()
A = []
for i in range(N):
    a = int(input())
    A.append(a)

a_max = 300001

UNITE = 0
N0 = 2**(a_max-1).bit_length()
data = [UNITE]*(2*N0)
# a_k の値を x に更新
def update(k, x):
    k += N0-1
    data[k] = x
    while k >= 0:
        k = (k - 1) // 2
        data[k] = max(data[2*k+1], data[2*k+2])
# 区間[l, r)の最小値
def query(l, r):
    L = l + N0; R = r + N0
    s = UNITE
    while L < R:
        if R & 1:
            R -= 1
            s = max(s, data[R-1])

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

for a in A:
    segmax = query(max(0,a-K),min(a_max,a+K)+1)
    update(a,segmax+1)

print(max(data))

Submission status: Accepted

Solution code:
class SegmentTree:
  def __init__(self, n, op, e):
    self.n = n
    self.op = op
    self.e = e
    self.size = 2 ** ((n - 1).bit_length())
    self.node = [self.e] * (2 * self.size)
 
  def build(self, array):
    for i in range(self.n):
      self.node[self.size + i] = array[i]
    for i in range(self.size - 1, 0, -1):
      self.node[i] = self.op(self.node[i << 1], self.node[(i << 1) + 1])
 
  def update(self, i, val):
    i += self.size
    self.node[i] = val
    while i > 1:
      i >>= 1
      self.node[i] = self.op(self.node[i << 1], self.node[(i << 1) + 1])
 
  def get(self, l, r):
    l, r = l + self.size, r + self.size
    res_l, res_r = self.e, self.e
    while l < r:
      if l & 1:
        res_l = self.op(res_l, self.node[l])
        l += 1
      if r & 1:
        r -= 1
        res_r = self.op(self.node[r], res_r) 
      l, r = l >> 1, r >> 1
    return self.op(res_l, res_r)
  
N,K = map(int, input().split())
A = list(int(input()) for _ in range(N))

max_len = max(A) + 2
ST = SegmentTree(max_len,max,0)
for a in A:
  a += 1
  l = max(1,a-K)
  r = min(max_len,a+K)
  ST.update(a,ST.get(l,r+1)+1)
print(ST.get(1,max_len))

Submission status: Accepted

Solution code:
n, k = map(int,input().split())
a = []
for i in range(n):
    a.append(int(input()))

dp = [[] for _ in range(n)]
#dp
dp[1].append(0)
M = 1
for i in range(1, n):
    m = M
    flg = 0
    while m > 0:
        for p in dp[m]:
            if abs(a[i]-a[p]) <= k:
                dp[m+1].append(i)
                flg = 1
                if m + 1 > M:
                    M = m+1
                break
        if flg == 1:
            break
        m -= 1
    if flg == 0:
        dp[1].append(i) #i
        
print(M)

Submission status: Accepted

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

def init(init_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:
        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
    
n,k = map(int,input().split())
a = [int(input()) for i in range(n)]
#n = int(input())
#a = tuple(map(int,input().split()))

#####単位元######
ide_ele = 0

#num:n以上の最小の2のべき乗
num =2**(max(a)-1).bit_length()
seg=[ide_ele]*2*num
#init(a)

ans = 0
max_a = max(a)

for i in range(n):
    tmp = query(max(0,a[i]-k),min(a[i]+k+1,max_a+1))
    #print(i,a[i],max(0,a[i]-k),min(a[i]+k,max(a)))
    update(a[i],tmp+1)
    #print(tmp)
    #print(st.query(0, max(a)))
    #ans = max(ans,tmp+1)
    #print(seg[0],k)
#print(seg)
#print(query(0,max(a)),seg[0])
print(seg[0])

Submission status: Accepted

Solution code:

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

#####ide_ele#####
ide_ele = 0
#################

class SegTree:
  """
  init(init_val, ide_ele): 配列init_valで初期化 O(N)
  update(k, x): k番目の値をxに更新 O(logN)
  query(l, r): 区間[l, r)をsegfuncしたものを返す O(logN)
  """
  def __init__(self, init_val, segfunc, ide_ele):
    """
    init_val: 配列の初期値
    segfunc: 区間にしたい操作
    ide_ele: 単位元
    n: 要素数
    num: n以上の最小の2のべき乗
    tree: セグメント木(1-index)
    """
    n = len(init_val)
    self.segfunc = segfunc
    self.ide_ele = ide_ele
    self.num = 1 << (n - 1).bit_length()
    self.tree = [ide_ele] * 2 * self.num
    # 配列の値を葉にセット
    for i in range(n):
      self.tree[self.num + i] = init_val[i]
    # 構築していく
    for i in range(self.num - 1, 0, -1):
      self.tree[i] = self.segfunc(self.tree[2 * i], self.tree[2 * i + 1])

  def update(self, k, x):
    """
    k番目の値をxに更新
    k: index(0-index)
    x: update value
    """
    k += self.num
    self.tree[k] = x
    while k > 1:
      self.tree[k >> 1] = self.segfunc(self.tree[k], self.tree[k ^ 1])
      k >>= 1

  def query(self, l, r):
    """
    [l, r)のsegfuncしたものを得る
    l: index(0-index)
    r: index(0-index)
    """
    res = self.ide_ele

    l += self.num
    r += self.num
    while l < r:
      if l & 1:
        res = self.segfunc(res, self.tree[l])
        l += 1
      if r & 1:
        res = self.segfunc(res, self.tree[r - 1])
      l >>= 1
      r >>= 1
    return res

def resolve():
  N, K = map(int, input().split(" "))
  max_range = (3000000 + 1)
  dp = [0] * max_range
  seg = SegTree(dp, segfunc, ide_ele)

  for _ in range(N):
    A = int(input())
    left = A-K
    right = A+K+1 #半開区間なので +1 してる
    seg.update(A, seg.query(left, right) + 1)

  print(seg.query(0, max_range+1))

if __name__ == "__main__":
  resolve()

Submission status: Accepted

Solution code:
import sys
import io, os
#input = sys.stdin.buffer.readline
input = io.BytesIO(os.read(0,os.fstat(0).st_size)).readline

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

class SegTree:
    def __init__(self, init_val, ide_ele, segfunc):
        self.n = len(init_val)
        self.num = 2**(self.n-1).bit_length()
        self.ide_ele = ide_ele
        self.segfunc = segfunc
        self.seg = [ide_ele]*2*self.num
        # set_val
        for i in range(self.n):
            self.seg[i+self.num] = init_val[i]
        # built
        for i in range(self.num-1, 0, -1):
            self.seg[i] = self.segfunc(self.seg[2*i], self.seg[2*i+1])

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

    def query(self, l, r):
        if r <= l:
            return self.ide_ele
        l += self.num
        r += self.num
        res = self.ide_ele
        while l < r:
            if r & 1:
                r -= 1
                res = self.segfunc(res, self.seg[r])
            if l & 1:
                res = self.segfunc(res, self.seg[l])
                l += 1
            l = l >> 1
            r = r >> 1
        return res

def segfunc(x, y):
    if x >= y:
        return x
    else:
        return y

maxa = 300005
#INF = 10**18
seg = SegTree([0]*maxa, 0, segfunc)

for a in A:
    l = max(0, a-k)
    r = min(a+k, maxa-1)
    t = seg.query(l, r+1)
    seg.update(a, t+1)
ans = seg.query(0, seg.n)
print(ans)

Submission status: Accepted

Solution code:
#参考https://qiita.com/takayg1/items/c811bd07c21923d7ec69

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

#####ide_ele初期値#####
ide_ele = 0
#################

class SegTree:
    """
    init(init_val, ide_ele): 配列init_valで初期化 O(N)
    update(k, x): k番目の値をxに更新 O(logN)
    query(l, r): 区間[l, r)をsegfuncしたものを返す O(logN)
    """
    def __init__(self, init_val, segfunc, ide_ele):
        """
        init_val: 配列の初期値
        segfunc: 区間にしたい操作
        ide_ele: 単位元
        n: 要素数
        num: n以上の最小の2のべき乗
        tree: セグメント木(1-index)
        """
        n = len(init_val)
        self.segfunc = segfunc
        self.ide_ele = ide_ele
        self.num = 1 << (n - 1).bit_length()
        self.tree = [ide_ele] * 2 * self.num
        # 配列の値を葉にセット
        for i in range(n):
            self.tree[self.num + i] = init_val[i]
        # 構築していく
        for i in range(self.num - 1, 0, -1):
            self.tree[i] = self.segfunc(self.tree[2 * i], self.tree[2 * i + 1])

    def update(self, k, x):
        """
        k番目の値をxに更新
        k: index(0-index)
        x: update value
        """
        k += self.num
        self.tree[k] = x
        while k > 1:
            self.tree[k >> 1] = self.segfunc(self.tree[k], self.tree[k ^ 1])
            k >>= 1

    def query(self, l, r):
        """
        [l, r)のsegfuncしたものを得る ※区間注意
        l: index(0-index)
        r: index(0-index)
        """
        res = self.ide_ele

        l += self.num
        r += self.num
        while l < r:
            if l & 1:
                res = self.segfunc(res, self.tree[l])
                l += 1
            if r & 1:
                res = self.segfunc(res, self.tree[r - 1])
            l >>= 1
            r >>= 1
        return res

N, K = map(int, input().split())
A = [int(input())+1 for _ in range(N)]
seg = SegTree([0 for i in range(300050)], segfunc, ide_ele)

answer = 0
for i in range(N):
    
    under = max(0,A[i]-K)
    upper = min(300050,A[i]+K)
    now = seg.query(under, upper+1)
    seg.update(A[i], now+1)
    
print(seg.query(0,300050))

Submission status: Accepted

Solution code:
# セグメント木
# segment tree
import sys
input = sys.stdin.readline

class segmented_tree:
    X_unit = 0
    X_f = lambda self, a, b: max(a,b)
    def __init__(self, N):
        self.N = N
        self.X = [self.X_unit] * (2*N)
        
    def build(self, seq):
        for i, x in enumerate(seq, self.N):
            self.X[i] = x 
        # 後ろから入れていく
        for i in range(self.N-1, 0, -1):
            self.X[i] = self.X_f(self.X[i<<1], self.X[i<<1|1])

    # 1点更新
    def set_val(self, i, x):
        i += self.N
        self.X[i] = x
        while i > 1:
            i >>= 1
            self.X[i] = self.X_f(self.X[i<<1],self.X[i<<1|1])
    
    # 区間取得
    def fold(self, l, r):
        l += self.N
        r += self.N
        vl = self.X_unit
        vr = self.X_unit
        # 外から決めていく
        while l < r:
            # print(l,r)
            if l & 1:
                vl = self.X_f(vl, self.X[l])
                l += 1
            if r & 1:
                r -= 1
                vr = self.X_f(vr, self.X[r])
            l >>= 1
            r >>= 1
        return self.X_f(vl,vr)

n,k = map(int, input().split())
As = [int(input()) for i in range(n)]

ans = 0
sg = segmented_tree(330000)

for a in As:
    l = max(0,a-k)
    r = min(300000,a+k)

    upd = sg.fold(l,r+1)
    ans = max(ans, upd+1)

    sg.set_val(a, upd+1)
print(ans)

Submission status: Accepted

Solution code:
# セグメント木
# segment tree
import sys
input = sys.stdin.readline

class segmented_tree:
    X_unit = 0
    X_f = lambda self, a, b: max(a,b)
    def __init__(self, N):
        self.N = N
        self.X = [self.X_unit] * (2*N)
        
    def build(self, seq):
        for i, x in enumerate(seq, self.N):
            self.X[i] = x 
        # 後ろから入れていく
        for i in range(self.N-1, 0, -1):
            self.X[i] = self.X_f(self.X[i<<1], self.X[i<<1|1])

    # 1点更新
    def set_val(self, i, x):
        i += self.N
        self.X[i] = x
        while i > 1:
            i >>= 1
            self.X[i] = self.X_f(self.X[i<<1],self.X[i<<1|1])
    
    # 区間取得
    def fold(self, l, r):
        l += self.N
        r += self.N
        vl = self.X_unit
        vr = self.X_unit
        # 外から決めていく
        while l < r:
            # print(l,r)
            if l & 1:
                vl = self.X_f(vl, self.X[l])
                l += 1
            if r & 1:
                r -= 1
                vr = self.X_f(vr, self.X[r])
            l >>= 1
            r >>= 1
        return self.X_f(vl,vr)

n,k = map(int, input().split())
As = [int(input()) for i in range(n)]
mx = 300001
ans = 0
sg = segmented_tree(330000)

for a in As:
    l = max(0,a-k)
    r = min(mx,a+k)

    upd = sg.fold(l,r+1)
    ans = max(ans, upd+1)

    sg.set_val(a, upd+1)
print(ans)

Submission status: Accepted

Solution code:
#参考https://qiita.com/takayg1/items/c811bd07c21923d7ec69

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

#####ide_ele初期値#####
ide_ele = 0
#################

class SegTree:
    """
    init(init_val, ide_ele): 配列init_valで初期化 O(N)
    update(k, x): k番目の値をxに更新 O(logN)
    query(l, r): 区間[l, r)をsegfuncしたものを返す O(logN)
    """
    def __init__(self, init_val, segfunc, ide_ele):
        """
        init_val: 配列の初期値
        segfunc: 区間にしたい操作
        ide_ele: 単位元
        n: 要素数
        num: n以上の最小の2のべき乗
        tree: セグメント木(1-index)
        """
        n = len(init_val)
        self.segfunc = segfunc
        self.ide_ele = ide_ele
        self.num = 1 << (n - 1).bit_length()
        self.tree = [ide_ele] * 2 * self.num
        # 配列の値を葉にセット
        for i in range(n):
            self.tree[self.num + i] = init_val[i]
        # 構築していく
        for i in range(self.num - 1, 0, -1):
            self.tree[i] = self.segfunc(self.tree[2 * i], self.tree[2 * i + 1])

    def update(self, k, x):
        """
        k番目の値をxに更新
        k: index(0-index)
        x: update value
        """
        k += self.num
        self.tree[k] = x
        while k > 1:
            self.tree[k >> 1] = self.segfunc(self.tree[k], self.tree[k ^ 1])
            k >>= 1

    def query(self, l, r):
        """
        [l, r)のsegfuncしたものを得る ※区間注意
        l: index(0-index)
        r: index(0-index)
        """
        res = self.ide_ele

        l += self.num
        r += self.num
        while l < r:
            if l & 1:
                res = self.segfunc(res, self.tree[l])
                l += 1
            if r & 1:
                res = self.segfunc(res, self.tree[r - 1])
            l >>= 1
            r >>= 1
        return res

N, K = map(int, input().split())
A = [int(input()) for _ in range(N)]
seg = SegTree([0 for i in range(300050)], segfunc, ide_ele)

answer = 0
for i in range(N):
    
    under = max(0,A[i]-K)
    upper = min(300050,A[i]+K)
    now = seg.query(under, upper+1)
    seg.update(A[i], now+1)
    
print(seg.query(0,300001))

Submission status: Accepted

Solution code:
import typing
import sys

# import re
import math
import collections
# import decimal
import bisect
import itertools
import fractions
# import functools
import copy
import heapq
import decimal
# import statistics
import queue
# import numpy as np

# sys.setrecursionlimit(10000001)
INF = 10 ** 16
# MOD = 10 ** 9 + 7
MOD = 998244353


def ni(): return int(sys.stdin.readline())
def ns(): return map(int, sys.stdin.readline().split())
def na(): return list(map(int, sys.stdin.readline().split()))


# ===CODE===

# https://github.com/not522/ac-library-python#install


def _ceil_pow2(n: int) -> int:
    x = 0
    while (1 << x) < n:
        x += 1

    return x


class SegTree:
    def __init__(self,
                 # segtreeで実行したい関数
                 op: typing.Callable[[typing.Any, typing.Any], typing.Any],
                 # モノイド：op関数に入れたとしても絶対に相手側の値が変わらないことが保証されるような値(足し算なら0、maxなら-INFなど)
                 e: typing.Any,
                 # segtreeにしたい配列を初期生成して突っ込む方式
                 v: typing.Union[int, typing.List[typing.Any]]) -> None:
        self._op = op
        self._e = e

        if isinstance(v, int):
            v = [e] * v

        self._n = len(v)
        self._log = _ceil_pow2(self._n)
        self._size = 1 << self._log
        self._d = [e] * (2 * self._size)

        for i in range(self._n):
            self._d[self._size + i] = v[i]
        for i in range(self._size - 1, 0, -1):
            self._update(i)

    # st[p]にxを代入
    def set(self, p: int, x: typing.Any) -> None:
        assert 0 <= p < self._n

        p += self._size
        self._d[p] = x
        for i in range(1, self._log + 1):
            self._update(p >> i)

    # st[p]を返す
    def get(self, p: int) -> typing.Any:
        assert 0 <= p < self._n

        return self._d[p + self._size]

    # op(st[l],...,st[r-1])を返す　l==rのときはe()を返す
    def prod(self, left: int, right: int) -> typing.Any:
        assert 0 <= left <= right <= self._n
        sml = self._e
        smr = self._e
        left += self._size
        right += self._size

        while left < right:
            if left & 1:
                sml = self._op(sml, self._d[left])
                left += 1
            if right & 1:
                right -= 1
                smr = self._op(self._d[right], smr)
            left >>= 1
            right >>= 1

        return self._op(sml, smr)

    # prod(0,len(a))のこと　l==rのときはe()を返す
    def all_prod(self) -> typing.Any:
        return self._d[1]

    # segtree上の二分探索 leftはベース fはleftより右側にあるst[left]に対して最初に条件を見たすindexを返す
    # 条件を満たすindexがないときはlen(a)が返ってくる
    # ex. segtree.max_right(x, lambda v: v < y) + 1  idx=xより右側にある最初のst[x]<st[v]となるvを返す()
    def max_right(self, left: int,
                  f: typing.Callable[[typing.Any], bool]) -> int:
        assert 0 <= left <= self._n
        assert f(self._e)

        if left == self._n:
            return self._n

        left += self._size
        sm = self._e

        first = True
        while first or (left & -left) != left:
            first = False
            while left % 2 == 0:
                left >>= 1
            if not f(self._op(sm, self._d[left])):
                while left < self._size:
                    left *= 2
                    if f(self._op(sm, self._d[left])):
                        sm = self._op(sm, self._d[left])
                        left += 1
                return left - self._size
            sm = self._op(sm, self._d[left])
            left += 1

        return self._n

    # segtree上の二分探索 rightはベース fはleftより左側にあるst[right]に対して最初に条件を見たすindexを返す
    # 条件を満たすindexがないときは0が返ってくる
    # ex. segtree.max_right(x, lambda v: v < y) + 1  idx=xより右側にある最初のst[x]<st[v]となるvを返す()
    def min_left(self, right: int,
                 f: typing.Callable[[typing.Any], bool]) -> int:
        assert 0 <= right <= self._n
        assert f(self._e)

        if right == 0:
            return 0

        right += self._size
        sm = self._e

        first = True
        while first or (right & -right) != right:
            first = False
            right -= 1
            while right > 1 and right % 2:
                right >>= 1
            if not f(self._op(self._d[right], sm)):
                while right < self._size:
                    right = 2 * right + 1
                    if f(self._op(self._d[right], sm)):
                        sm = self._op(self._d[right], sm)
                        right -= 1
                return right + 1 - self._size
            sm = self._op(self._d[right], sm)

        return 0

    def _update(self, k: int) -> None:
        self._d[k] = self._op(self._d[2 * k], self._d[2 * k + 1])


def main():
    n, k = ns()
    a = [ni() for _ in range(n)]

    dp = [0 for _ in range(3*10**5+1)]

    st = SegTree(max, -1, dp)

    for ai in a:
        cnt = st.prod(max(0, ai-k), min(ai+k+1, 3*10**5+1))
        st.set(ai, cnt+1)
    ans = st.all_prod()
    print(ans)


if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
import sys, math
import io, os
#data = io.BytesIO(os.read(0,os.fstat(0).st_size)).readline
from bisect import bisect_left as bl, bisect_right as br, insort
from heapq import heapify, heappush, heappop
from collections import defaultdict as dd, deque, Counter
# from itertools import permutations,combinations
def data(): return sys.stdin.readline().strip()
def mdata(): return list(map(int, data().split()))
def outl(var): sys.stdout.write('\n'.join(map(str, var)) + '\n')
def out(var): sys.stdout.write(str(var) + '\n')
from decimal import Decimal
# from fractions import Fraction
# sys.setrecursionlimit(100000)
mod = 998244353
INF=float('inf')


def construct_sum(segtree,a,n,func=max):
    for i in range(n):
        segtree[n + i] = a[i]
    for i in range(n - 1, 0, -1):
        segtree[i] = func(segtree[2 * i], segtree[2 * i + 1])

def update(pos, x, func=max):
    pos += n-1
    segtree[pos] = x
    while (pos>1):
        pos>>=1
        segtree[pos] = func(segtree[2 * pos], segtree[2 * pos + 1])

def get(l, r, func=max):
    l += n-1
    r += n-1
    s = 0
    while (l <= r):
        if l & 1:
            s = func(segtree[l],s)
            l+=1
        if (r+1) & 1:
            s = func(segtree[r],s)
            r-=1
        l >>= 1
        r >>= 1
    return s

n,k=mdata()
a=[int(data()) for i in range(n)]
n=max(a)+1
segtree = [0]*(2*n)
construct_sum(segtree,[0]*n,n)
ans=0
for i in a:
    a1=get(max(i-k+1,1),min(i+k+1,n))+1
    update(i+1,a1)
    ans=max(ans,a1)
out(ans)

Submission status: Accepted

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

n,k = map(int, input().split())
As = [int(input()) for i in range(n)]

# N: 処理する区間の長さ

INF = 0

mx = 300001
LV = (mx-1).bit_length()
N0 = 2**LV
data = [INF]*(2*N0)
lazy = [None]*(2*N0)

# 伝搬対象の区間を求める
def gindex(l, r):
    L = (l + N0) >> 1; R = (r + N0) >> 1
    lc = 0 if l & 1 else (L & -L).bit_length()
    rc = 0 if r & 1 else (R & -R).bit_length()
    for i in range(LV):
        if rc <= i:
            yield R
        if L < R and lc <= i:
            yield L
        L >>= 1; R >>= 1

# 遅延伝搬処理
def propagates(*ids):
    for i in reversed(ids):
        v = lazy[i-1]
        if v is None:
            continue
        lazy[2*i-1] = data[2*i-1] = lazy[2*i] = data[2*i] = v
        lazy[i-1] = None

# 区間[l, r)をxで更新
def update(l, r, x):
    *ids, = gindex(l, r)
    propagates(*ids)

    L = N0 + l; R = N0 + r
    while L < R:
        if R & 1:
            R -= 1
            lazy[R-1] = data[R-1] = x
        if L & 1:
            lazy[L-1] = data[L-1] = x
            L += 1
        L >>= 1; R >>= 1
    for i in ids:
        data[i-1] = max(data[2*i-1], data[2*i])

# 区間[l, r)内の最小値を求める
def query(l, r):
    propagates(*gindex(l, r))
    L = N0 + l; R = N0 + r

    s = INF
    while L < R:
        if R & 1:
            R -= 1
            s = max(s, data[R-1])
        if L & 1:
            s = max(s, data[L-1])
            L += 1
        L >>= 1; R >>= 1
    return s

ans = 0
update(As[0],As[0]+1,1)
for i, a in enumerate(As[1:]):
    l = max(0,a-k)
    r = min(mx,a+k)
    upd = query(l,r+1)
    if upd == -1:continue
    # print("i",i,"a",a,"upd",upd,"l",l,"r",r)
    update(a, a+1, upd+1)
    ans = max(ans, upd+1)
print(ans)

Submission status: Accepted

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

n,k = map(int, input().split())
As = [int(input()) for i in range(n)]

# N: 処理する区間の長さ

INF = 0

mx = 300001
LV = (mx-1).bit_length()
N0 = 2**LV
data = [INF]*(2*N0)
lazy = [None]*(2*N0)

# 伝搬対象の区間を求める
def gindex(l, r):
    L = (l + N0) >> 1; R = (r + N0) >> 1
    lc = 0 if l & 1 else (L & -L).bit_length()
    rc = 0 if r & 1 else (R & -R).bit_length()
    for i in range(LV):
        if rc <= i:
            yield R
        if L < R and lc <= i:
            yield L
        L >>= 1; R >>= 1

# 遅延伝搬処理
def propagates(*ids):
    for i in reversed(ids):
        v = lazy[i-1]
        if v is None:
            continue
        lazy[2*i-1] = data[2*i-1] = lazy[2*i] = data[2*i] = v
        lazy[i-1] = None

# 区間[l, r)をxで更新
def update(l, r, x):
    *ids, = gindex(l, r)
    propagates(*ids)

    L = N0 + l; R = N0 + r
    while L < R:
        if R & 1:
            R -= 1
            lazy[R-1] = data[R-1] = x
        if L & 1:
            lazy[L-1] = data[L-1] = x
            L += 1
        L >>= 1; R >>= 1
    for i in ids:
        data[i-1] = max(data[2*i-1], data[2*i])

# 区間[l, r)内の最小値を求める
def query(l, r):
    propagates(*gindex(l, r))
    L = N0 + l; R = N0 + r

    s = INF
    while L < R:
        if R & 1:
            R -= 1
            s = max(s, data[R-1])
        if L & 1:
            s = max(s, data[L-1])
            L += 1
        L >>= 1; R >>= 1
    return s

update(As[0],As[0]+1,1)
for i, a in enumerate(As[1:]):
    l = max(0,a-k)
    r = min(mx,a+k)
    upd = query(l,r+1)
    if upd == -1:continue
    # print("i",i,"a",a,"upd",upd,"l",l,"r",r)
    update(a, a+1, upd+1)

ans = 0
for a in set(As):
    ans = max(ans,query(a,a+1))
print(ans)

Submission status: Accepted

Solution code:

class SegmentTree():
  def __init__(self, n, oper, e):
    self.n = n
    self.oper = oper
    self.e = e
    self.log = (n - 1).bit_length()
    self.size = 1 << self.log
    self.data = [e] * (2 * self.size)

  def update(self, k):
    self.data[k] = self.oper(self.data[2 * k], self.data[2 * k + 1])

  def build(self, arr):
    #assert len(arr) <= self.n
    for i in range(self.n):
      self.data[self.size + i] = arr[i]
    for i in range(self.size-1,0,-1):
      self.update(i)

  def set(self, p, x):
    #assert 0 <= p < self.n
    p += self.size
    self.data[p] = x
    for i in range(1, self.log + 1):
      self.update(p >> i)

  def get(self, p):
    #assert 0 <= p < self.n
    return self.data[p + self.size]

  def prod(self, l, r):
    #assert 0 <= l <= r <= self.n
    sml = smr = self.e
    l += self.size
    r += self.size
    while l < r:
      if l & 1:
        sml = self.oper(sml, self.data[l])
        l += 1
      if r & 1:
        r -= 1
        smr = self.oper(self.data[r], smr)
      l >>= 1
      r >>= 1
    return self.oper(sml, smr)

  def all_prod(self):
    return self.data[1]

  def max_right(self, l, f):
    #assert 0 <= l <= self.n
    #assert f(self.)
    if l == self.n: return self.n
    l += self.size
    sm = self.e
    while True:
      while l % 2 == 0: l >>= 1
      if not f(self.oper(sm, self.data[l])):
        while l < self.size:
          l = 2 * l
          if f(self.oper(sm, self.data[l])):
            sm = self.oper(sm, self.data[l])
            l += 1
        return l - self.size
      sm = self.oper(sm, self.data[l])
      l += 1
      if (l & -l) == l: break
    return self.n

  def min_left(self, r, f):
    #assert 0 <= r <= self.n
    #assert f(self.)
    if r == 0: return 0
    r += self.size
    sm = self.e
    while True:
      r -= 1
      while r > 1 and (r % 2): r >>= 1
      if not f(self.oper(self.data[r], sm)):
        while r < self.size:
          r = 2 * r + 1
          if f(self.oper(self.data[r], sm)):
            sm = self.oper(self.data[r], sm)
            r -= 1
        return r + 1 - self.size
      sm = self.oper(self.data[r], sm)
      if (r & -r) == r: break
    return 0

#import sys
#input = sys.stdin.readline

n,k=map(int,input().split())
a=[0]*n
for i in range(n):
    a[i]=int(input())
maxa=max(a)

st = SegmentTree(maxa+1,max,0)
#st.build(a)


ans=0
for i in range(n):
    l=max(a[i]-k,0)
    r=min(a[i]+k,300000)
    tmp=st.prod(l,r+1)+1
#    print(i,l,r+1,tmp)
    ans=max(ans,tmp)
    st.set(a[i],tmp)

print(ans)