Input: nums =[4,2,1,4,3,4,5,8,15], k =3Output: 5Explanation:
The longest subsequence that meets the requirements is[1,3,4,5,8].The subsequence has a length of 5, so we return5.Note that the subsequence [1,3,4,5,8,15] does not meet the requirements because 15-8=7is larger than 3.
Input: nums =[7,4,5,1,8,12,4,7], k =5Output: 4Explanation:
The longest subsequence that meets the requirements is[4,5,8,12].The subsequence has a length of 4, so we return4.
Input: nums =[1,5], k =1Output: 1Explanation:
The longest subsequence that meets the requirements is[1].The subsequence has a length of 1, so we return1.
To efficiently find the longest increasing subsequence with adjacent difference at most k, we use a segment tree (or binary indexed tree) to keep track of the maximum dp value for all possible previous numbers in the valid range. For each number, we query the segment tree for the best previous result and update the tree with the new dp value.
classSegmentTree {
vector<int> tree;
int n;
public: SegmentTree(int size) : n(size), tree(2*size) {}
voidupdate(int i, int val) {
i += n;
tree[i] = max(tree[i], val);
for (i /=2; i >0; i /=2)
tree[i] = max(tree[2*i], tree[2*i+1]);
}
intquery(int l, int r) {
int res =0;
for (l += n, r += n; l < r; l /=2, r /=2) {
if (l%2) res = max(res, tree[l++]);
if (r%2) res = max(res, tree[--r]);
}
return res;
}
};
classSolution {
public:int lengthOfLIS(vector<int>& nums, int k) {
set<int> s(nums.begin(), nums.end());
vector<int> vals(s.begin(), s.end());
unordered_map<int, int> idx;
for (int i =0; i < vals.size(); ++i) idx[vals[i]] = i;
SegmentTree st(vals.size());
int ans =0;
for (int x : nums) {
int l = lower_bound(vals.begin(), vals.end(), x-k) - vals.begin();
int r = lower_bound(vals.begin(), vals.end(), x) - vals.begin();
int best = st.query(l, r);
int cur = best +1;
st.update(idx[x], cur);
ans = max(ans, cur);
}
return ans;
}
};
import java.util.*;
classSegmentTree {
privateint[] tree;
privateint n;
publicSegmentTree(int size) {
this.n= size;
this.tree=newint[2 * size];
}
publicvoidupdate(int i, int val) {
i += n;
tree[i]= Math.max(tree[i], val);
for (i /= 2; i > 0; i /= 2) {
tree[i]= Math.max(tree[2*i], tree[2*i+1]);
}
}
publicintquery(int l, int r) {
int res = 0;
for (l += n, r += n; l < r; l /= 2, r /= 2) {
if (l % 2 == 1) res = Math.max(res, tree[l++]);
if (r % 2 == 1) res = Math.max(res, tree[--r]);
}
return res;
}
}
classSolution {
publicintlengthOfLIS(int[] nums, int k) {
Set<Integer> valSet =new TreeSet<>();
for (int num : nums) {
valSet.add(num);
}
List<Integer> vals =new ArrayList<>(valSet);
Map<Integer, Integer> idx =new HashMap<>();
for (int i = 0; i < vals.size(); i++) {
idx.put(vals.get(i), i);
}
SegmentTree st =new SegmentTree(vals.size());
int ans = 0;
for (int x : nums) {
int l = Collections.binarySearch(vals, x - k);
if (l < 0) l =-l - 1;
int r = Collections.binarySearch(vals, x);
if (r < 0) r =-r - 1;
int best = st.query(l, r);
int cur = best + 1;
st.update(idx.get(x), cur);
ans = Math.max(ans, cur);
}
return ans;
}
}
classSegmentTree(size: Int) {
privateval tree = IntArray(2 * size)
privateval n = size
funupdate(i: Int, `val`: Int) {
var idx = i + n
tree[idx] = maxOf(tree[idx], `val`)
idx /=2while (idx > 0) {
tree[idx] = maxOf(tree[2 * idx], tree[2 * idx + 1])
idx /=2 }
}
funquery(l: Int, r: Int): Int {
var res = 0var left = l + n
var right = r + n
while (left < right) {
if (left % 2==1) {
res = maxOf(res, tree[left])
left++ }
if (right % 2==1) {
right-- res = maxOf(res, tree[right])
}
left /=2 right /=2 }
return res
}
}
classSolution {
funlengthOfLIS(nums: IntArray, k: Int): Int {
val vals = nums.toSet().sorted()
val idx = vals.withIndex().associate { it.value to it.index }
val st = SegmentTree(vals.size)
var ans = 0for (x in nums) {
val l = vals.binarySearch(x - k).let { if (it < 0) -it - 1elseit }
val r = vals.binarySearch(x).let { if (it < 0) -it - 1elseit }
val best = st.query(l, r)
val cur = best + 1 st.update(idx[x]!!, cur)
ans = maxOf(ans, cur)
}
return ans
}
}
classSegmentTree:
def__init__(self, size):
self.N =1while self.N < size:
self.N <<=1 self.tree = [0] * (2*self.N)
defupdate(self, i, val):
i += self.N
self.tree[i] = max(self.tree[i], val)
while i >1:
i //=2 self.tree[i] = max(self.tree[2*i], self.tree[2*i+1])
defquery(self, l, r):
res =0 l += self.N
r += self.N
while l < r:
if l %2:
res = max(res, self.tree[l])
l +=1if r %2:
r -=1 res = max(res, self.tree[r])
l //=2 r //=2return res
classSolution:
deflengthOfLIS(self, nums: list[int], k: int) -> int:
vals = sorted(set(nums))
idx = {v: i for i, v in enumerate(vals)}
st = SegmentTree(len(vals))
ans =0for x in nums:
l = bisect.bisect_left(vals, x-k)
r = bisect.bisect_left(vals, x)
best = st.query(l, r)
cur = best +1 st.update(idx[x], cur)
ans = max(ans, cur)
return ans
use std::collections::{HashMap, BTreeSet};
structSegmentTree {
tree: Vec<i32>,
n: usize,
}
impl SegmentTree {
fnnew(size: usize) -> Self {
Self {
tree: vec![0; 2* size],
n: size,
}
}
fnupdate(&mut self, mut i: usize, val: i32) {
i += self.n;
self.tree[i] = self.tree[i].max(val);
i /=2;
while i >0 {
self.tree[i] = self.tree[2* i].max(self.tree[2* i +1]);
i /=2;
}
}
fnquery(&self, mut l: usize, mut r: usize) -> i32 {
letmut res =0;
l += self.n;
r += self.n;
while l < r {
if l %2==1 {
res = res.max(self.tree[l]);
l +=1;
}
if r %2==1 {
r -=1;
res = res.max(self.tree[r]);
}
l /=2;
r /=2;
}
res
}
}
impl Solution {
pubfnlength_of_lis(nums: Vec<i32>, k: i32) -> i32 {
let val_set: BTreeSet<i32>= nums.iter().cloned().collect();
let vals: Vec<i32>= val_set.into_iter().collect();
let idx: HashMap<i32, usize>= vals.iter()
.enumerate()
.map(|(i, &v)| (v, i))
.collect();
letmut st = SegmentTree::new(vals.len());
letmut ans =0;
for x in nums {
let l = vals.binary_search(&(x - k))
.unwrap_or_else(|i| i);
let r = vals.binary_search(&x)
.unwrap_or_else(|i| i);
let best = st.query(l, r);
let cur = best +1;
st.update(idx[&x], cur);
ans = ans.max(cur);
}
ans
}
}