#include <iostream>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <functional>
#include <iterator>
#include <numeric>
#include <cstdint>
#include <cmath>
#include <bitset>
#include <string>
#include <list>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <random>
#include <chrono>
#include <cassert>

#define N_TIMES(i, n)     for ( uint64_t i = 0;     i <  n; ++i )
#define N_TIMES_REV(i, n) for (  int64_t i = n - 1; i >= 0; --i )

template<typename T> using maximum_heap = std::priority_queue<T, std::vector<T>, std::less<T>>;
template<typename T> using minimum_heap = std::priority_queue<T, std::vector<T>, std::greater<T>>;

template<typename T>
std::istream& operator>>(std::istream &is, std::vector<T> &v)
{
  for (typename std::vector<T>::size_type i = 0; i < v.size(); ++i) {
    is >> v[i];
  }
  return is;
}

template<typename INDEX_TYPE, typename VALUE_TYPE, const VALUE_TYPE &Undefined, class Compare = std::less<VALUE_TYPE>>
class RangeMinimumQueryBase {
private:
  std::vector<VALUE_TYPE> segment_tree;
  INDEX_TYPE N, M;

  VALUE_TYPE _min(VALUE_TYPE a, VALUE_TYPE b) const
  {
    return (Compare()(a, b)) ? a : b;
  }

  INDEX_TYPE _upper_bound_by_power_of_2(INDEX_TYPE n) const
  {
    return 1 << static_cast<INDEX_TYPE>(
      ::ceill(::log2l(static_cast<long double>(n)))
    );
  }

  VALUE_TYPE _build_segment_tree(const std::vector<VALUE_TYPE> &a, INDEX_TYPE i = 0)
  {
    if (i >= (M << 1)) {
      return Undefined;
    }

    if (segment_tree[i] != Undefined) {
      return segment_tree[i];
    }

    segment_tree[i] = _min(
      _build_segment_tree(a, 2 * i + 1),
      _build_segment_tree(a, 2 * i + 2)
    );

    return segment_tree[i];
  }

  bool _update(INDEX_TYPE index, VALUE_TYPE value, INDEX_TYPE lb, INDEX_TYPE ub, INDEX_TYPE i)
  {
    if (index < lb || ub <= index) {
      return false;
    }

    if (lb == index && ub - lb == 1) {
      segment_tree[i] = value;
      return true;
    }

    INDEX_TYPE mid = (lb + ub) >> 1;
    bool f = _update(index, value, lb,  mid, 2 * i + 1);
    bool g = _update(index, value, mid, ub,  2 * i + 2);
    segment_tree[i] = _min(segment_tree[2 * i + 1], segment_tree[2 * i + 2]);
    return f || g;
  }

  VALUE_TYPE _find(INDEX_TYPE left, INDEX_TYPE right, INDEX_TYPE lb, INDEX_TYPE ub, INDEX_TYPE i)
  {
    if (right <= lb || ub <= left) {
      return Undefined;
    }

    if (left <= lb && ub <= right) {
      return segment_tree[i];
    }

    INDEX_TYPE mid = (lb + ub) >> 1;
    return _min(
      _find(left, right, lb,  mid, 2 * i + 1),
      _find(left, right, mid, ub,  2 * i + 2)
    );
  }

public:
  RangeMinimumQueryBase(const std::vector<VALUE_TYPE> &a)
  {
    N = a.size();
    M = _upper_bound_by_power_of_2(N);

    segment_tree = std::vector<VALUE_TYPE>(M << 1, Undefined);
    for (INDEX_TYPE n = 0; n < N; ++n) {
      segment_tree[n + (M - 1)] = a[n];
    }

    _build_segment_tree(a);
  }

  bool update(INDEX_TYPE index, VALUE_TYPE value)
  {
    return _update(index, value, 0, M, 0);
  }

  VALUE_TYPE find(INDEX_TYPE left, INDEX_TYPE right)
  {
    return _find(left, right, 0, M, 0);
  }
  
  std::vector<VALUE_TYPE> operator()() const {
    return segment_tree;
  }
};

const uint64_t Undefined = 0;

using RangeMaximumQuery = RangeMinimumQueryBase<uint64_t, uint64_t, Undefined, std::greater<uint64_t>>;

using namespace std;

int main()
{
  uint64_t N, K;
  cin >> N >> K;

  vector<uint64_t> A(N);
  cin >> A;

  uint64_t M = *max_element(A.begin(), A.end());

  RangeMaximumQuery rmq(vector<uint64_t>(M + K + 1, 0));
  N_TIMES(n, N) {
    uint64_t lb = A[n] > K ? A[n] - K : 0;
    uint64_t ub = A[n] + K > M ? M : A[n] + K;

    rmq.update(A[n], rmq.find(lb, ub + 1) + 1);
  }
  cout << rmq.find(0, M + 1) << endl;

  return 0;
}

Measured memory_bytes: 26688