#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
using namespace std;
using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
using i8 = int8_t;
using i16 = int16_t;
using i32 = int32_t;
using i64 = int64_t;
using vi = vector<int>;
constexpr char newl = '\n';
constexpr double eps = 1e-10;
template <typename T1, typename T2>
inline void chmin(T1& a, T2 b) {
  if (a > b) a = b;
}
template <typename T1, typename T2>
inline void chmax(T1& a, T2 b) {
  if (a < b) a = b;
}
template <class T>
bool lcmp(const pair<T, T>& l, const pair<T, T>& r) {
  return l.first < r.first;
}
template <class T>
istream& operator>>(istream& i, vector<T>& v) {
  for (int j = (0); j < ((int)(v).size()); j++) i >> v[j];
  return i;
}
template <class A, class B>
istream& operator>>(istream& i, pair<A, B>& p) {
  return i >> p.first >> p.second;
}
template <class A, class B, class C>
istream& operator>>(istream& i, tuple<A, B, C>& t) {
  return i >> get<0>(t) >> get<1>(t) >> get<2>(t);
}
template <class T>
ostream& operator<<(ostream& o, const vector<T>& v) {
  for (int i = (0); i < (v.size()); i++) {
    o << v[i] << ' ';
  }
  o << newl;
  return o;
}
template <class T1, class T2>
ostream& operator<<(ostream& o, const map<T1, T2>& m) {
  for (auto& p : m) {
    o << p.first << ": " << p.second << newl;
  }
  o << newl;
  return o;
}
template <class Element, class Lazy>
class SegmentTree {
  using A = function<Element(const Element&, const Element&)>;
  using B = function<void(Element&, const Lazy&, int elementCount)>;
  using C = function<void(Lazy&, const Lazy&)>;
  using ECallback = function<void(const Element&, const Lazy&)>;
  constexpr int parent(int v) { return ((v + 1) >> 1) - 1; }
  constexpr bool hasChild(int v) { return v <= size - 2; }
  constexpr int lchild(int v) { return ((v + 1) << 1) - 1; }
  constexpr int rchild(int v) { return (v + 1) << 1; }

 public:
  SegmentTree(int size, A mergeElements, B applyLazyToElement, C mergeLazies)
      : mergeTT(mergeElements),
        mergeTE(applyLazyToElement),
        mergeEE(mergeLazies) {
    int n = 1;
    while (n < size) n <<= 1;
    this->size = n;
    int segCount = n * 2 - 1;
    es = vector<Element>(segCount);
    ls = vector<Lazy>(segCount);
    lazyFlag = vector<bool>(segCount, false);
    lefts = vector<int>(segCount);
    rights = vector<int>(segCount);
    mp = vector<int>(segCount);
    for (int i = 0, l = 0, w = n; i < segCount; i++) {
      lefts[i] = l;
      rights[i] = lefts[i] + w;
      mp[i] = lefts[i] + (w >> 1);
      if (rights[i] >= n) {
        w >>= 1;
        l = 0;
      } else {
        l += w;
      }
    }
  }
  void Set(const vector<Element>& vs) {
    int index = 0;
    while (hasChild(index)) index = lchild(index);
    for (int i = (0); i < (min<int>(vs.size(), this->size)); i++) {
      es[index++] = vs[i];
    }
    recalc();
  }
  void Set(const Lazy& value, int left, int right, int segIndex = 0) {
    if (left <= lefts[segIndex] && rights[segIndex] <= right) {
      add(segIndex, value);
      resolve(segIndex);
    } else {
      resolve(segIndex);
      auto l = lchild(segIndex), r = rchild(segIndex);
      if (left < mp[segIndex]) {
        Set(value, left, right, l);
      } else {
        resolve(l);
      }
      if (mp[segIndex] < right) {
        Set(value, left, right, r);
      } else {
        resolve(r);
      }
      es[segIndex] = mergeTT(es[l], es[r]);
    }
  }
  Element Get(int left, int right, int segIndex = 0) {
    if (right <= left) return Element();
    resolve(segIndex);
    if (left <= lefts[segIndex] && rights[segIndex] <= right) {
      return es[segIndex];
    } else {
      if (left < mp[segIndex]) {
        if (mp[segIndex] < right) {
          return mergeTT(Get(left, right, lchild(segIndex)),
                         Get(left, right, rchild(segIndex)));
        }
        return Get(left, right, lchild(segIndex));
      } else if (mp[segIndex] < right) {
        return Get(left, right, rchild(segIndex));
      }
    }
  }
  void Print(ECallback c) {
    for (int i = (0); i < (es.size()); i++) {
      c(es[i], ls[i]);
      if (((i + 2) & (i + 1)) == 0) {
        cout << "." << newl;
      }
    }
  }

 protected:
  void resolve(int segIndex) {
    if (!lazyFlag[segIndex]) return;
    mergeTE(es[segIndex], ls[segIndex], rights[segIndex] - lefts[segIndex]);
    if (hasChild(segIndex)) {
      auto l = lchild(segIndex), r = rchild(segIndex);
      add(l, ls[segIndex]);
      add(r, ls[segIndex]);
    }
    ls[segIndex] = Lazy();
    lazyFlag[segIndex] = false;
  }
  void add(int segIndex, const Lazy& value) {
    if (lazyFlag[segIndex]) {
      mergeEE(ls[segIndex], value);
    } else {
      ls[segIndex] = value;
      lazyFlag[segIndex] = true;
    }
  }
  void recalc(int segIndex = 0) {
    if (hasChild(segIndex)) {
      recalc(lchild(segIndex));
      recalc(rchild(segIndex));
      es[segIndex] = mergeTT(es[lchild(segIndex)], es[rchild(segIndex)]);
    }
  }
  A mergeTT;
  B mergeTE;
  C mergeEE;
  vector<Element> es;
  vector<Lazy> ls;
  vector<bool> lazyFlag;
  vector<int> lefts, rights, mp;
  int size;
};
signed main() {
  cin.tie(0);
  ios_base::sync_with_stdio(false);
  int N, K;
  cin >> N >> K;
  struct Elem {
    i64 Max = 0;
  };
  struct Lazy {
    i64 Set = 0;
  };
  auto c1 = [](const Elem& l, const Elem& r) -> Elem {
    Elem o;
    o.Max = max(l.Max, r.Max);
    return o;
  };
  auto c2 = [](Elem& l, const Lazy& r, int elementCount) -> void {
    l.Max = r.Set;
  };
  auto c3 = [](Lazy& l, const Lazy& r) -> void { l.Set = r.Set; };
  auto qSet = [](i64 value) -> Lazy {
    Lazy l;
    l.Set = value;
    return l;
  };
  SegmentTree<Elem, Lazy> st(300001, c1, c2, c3);
  for (int i = (0); i < (N); i++) {
    int a;
    cin >> a;
    int l = max(a - K, 0), r = min(a + K + 1, 300001);
    int v = st.Get(l, r).Max + 1;
    st.Set(qSet(v), a, a + 1);
  }
  cout << st.Get(0, N).Max;
}
