#include <bits/stdc++.h>
#pragma GCC optimize("O3")
#pragma GCC target("avx2,avx")
#pragma GCC optimize("unroll-loops")
using namespace std;
string YES[2] = {"NO", "YES"};
string Yes[2] = {"No", "Yes"};
string yes[2] = {"no", "yes"};
template <class T>
using pq = priority_queue<T>;
template <class T>
using pqg = priority_queue<T, vector<T>, greater<T>>;
int scan() { return getchar(); }
void scan(int &a) { cin >> a; }
void scan(long long &a) { cin >> a; }
void scan(char &a) { cin >> a; }
void scan(double &a) { cin >> a; }
void scan(string &a) { cin >> a; }
template <class T, class S>
void scan(pair<T, S> &p) {
  scan(p.first), scan(p.second);
}
template <class T>
void scan(vector<T> &);
template <class T>
void scan(vector<T> &a) {
  for (auto &i : a) scan(i);
}
template <class T>
void scan(T &a) {
  cin >> a;
}
void IN() {}
template <class Head, class... Tail>
void IN(Head &head, Tail &...tail) {
  scan(head);
  IN(tail...);
}
template <class T, class S>
inline bool chmax(T &a, S b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T, class S>
inline bool chmin(T &a, S b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
vector<int> iota(int n) {
  vector<int> a(n);
  iota(begin(a), end(a), 0);
  return a;
}
template <typename T>
vector<int> iota(vector<T> &a, bool greater = false) {
  vector<int> res(a.size());
  iota(begin(res), end(res), 0);
  sort(begin(res), end(res), [&](int i, int j) {
    if (greater) return a[i] > a[j];
    return a[i] < a[j];
  });
  return res;
}
vector<pair<long long, long long>> factor(long long x) {
  vector<pair<long long, long long>> ans;
  for (long long i = 2; i * i <= x; i++)
    if (x % i == 0) {
      ans.push_back({i, 1});
      while ((x /= i) % i == 0) ans.back().second++;
    }
  if (x != 1) ans.push_back({x, 1});
  return ans;
}
template <class T>
vector<T> divisor(T x) {
  vector<T> ans;
  for (T i = 1; i * i <= x; i++)
    if (x % i == 0) {
      ans.push_back(i);
      if (i * i != x) ans.push_back(x / i);
    }
  return ans;
}
template <typename T>
void zip(vector<T> &x) {
  vector<T> y = x;
  sort(begin(y), end(y));
  for (int i = 0; i < x.size(); ++i) {
    x[i] = distance((y).begin(), lower_bound(begin(y), end(y), (x[i])));
  }
}
int popcount(long long x) { return __builtin_popcountll(x); }
struct Setup_io {
  Setup_io() {
    ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cout << fixed << setprecision(15);
  }
} setup_io;
int in() {
  int x;
  cin >> x;
  return x;
}
long long lin() {
  unsigned long long x;
  cin >> x;
  return x;
}
template <typename T>
struct edge {
  int from, to;
  T cost;
  int id;
  edge(int to, T cost) : from(-1), to(to), cost(cost) {}
  edge(int from, int to, T cost) : from(from), to(to), cost(cost) {}
  edge(int from, int to, T cost, int id)
      : from(from), to(to), cost(cost), id(id) {}
  edge &operator=(const int &x) {
    to = x;
    return *this;
  }
  operator int() const { return to; }
};
template <typename T>
using Edges = vector<edge<T>>;
using Tree = vector<vector<int>>;
using Graph = vector<vector<int>>;
template <class T>
using Wgraph = vector<vector<edge<T>>>;
Graph getG(int n, int m = -1, bool directed = false, int margin = 1) {
  Tree res(n);
  if (m == -1) m = n - 1;
  while (m--) {
    int a, b;
    cin >> a >> b;
    a -= margin, b -= margin;
    res[a].emplace_back(b);
    if (!directed) res[b].emplace_back(a);
  }
  return move(res);
}
template <class T>
Wgraph<T> getWg(int n, int m = -1, bool directed = false, int margin = 1) {
  Wgraph<T> res(n);
  if (m == -1) m = n - 1;
  while (m--) {
    int a, b;
    T c;
    cin >> a >> b >> c;
    a -= margin, b -= margin;
    res[a].emplace_back(b, c);
    if (!directed) res[b].emplace_back(a, c);
  }
  return move(res);
}
template <class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  for (auto &e : v) cout << e << " ";
  cout << endl;
  return os;
}
template <class T, class S>
ostream &operator<<(ostream &os, const pair<T, S> &p) {
  cout << "(" << p.first << ", " << p.second << ")";
  return os;
}
template <class S, class T>
string to_string(pair<S, T> p) {
  return "(" + to_string(p.first) + "," + to_string(p.second) + ")";
}
template <class A>
string to_string(A v) {
  if (v.empty()) return "{}";
  string ret = "{";
  for (auto &x : v) ret += to_string(x) + ",";
  ret.back() = '}';
  return ret;
}
void dump() { cerr << endl; }
template <class Head, class... Tail>
void dump(Head head, Tail... tail) {
  cerr << to_string(head) << " ";
  dump(tail...);
}
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int rnd(int n) { return uniform_int_distribution<int>(0, n - 1)(rng); }
long long rndll(long long n) {
  return uniform_int_distribution<long long>(0, n - 1)(rng);
}
template <typename T>
static constexpr T inf = numeric_limits<T>::max() / 2;
template <typename T = long long>
struct SegmentTree {
  using F = function<T(T, T)>;
  SegmentTree(int n, const F f, const T &unit)
      : f(f), unit(unit), sz(n - 1 ? 1 << (32 - __builtin_clz(n - 1)) : 1) {
    seg.assign(2 * sz, unit);
  }
  SegmentTree(vector<T> &a, const F f, const T &unit)
      : f(f),
        sz((int)a.size() > 1 ? 1 << (32 - __builtin_clz(a.size() - 1)) : 1),
        unit(unit) {
    int n0 = a.size();
    seg.assign(2 * sz, unit);
    for (int i = 0; i < n0; ++i) seg[i + sz] = a[i];
    for (int i = sz - 1; i > 0; --i) seg[i] = f(seg[i << 1], seg[(i << 1) | 1]);
  }
  const int sz;
  vector<T> seg;
  const F f;
  const T unit;
  void set(int k, T x) { seg[k + sz] = x; }
  void build() {
    for (int i = sz - 1; i > 0; --i) seg[i] = f(seg[i << 1], seg[(i << 1) | 1]);
  }
  T query(int l, int r) {
    T x = unit;
    for (int d = r - l; d >= 1; d = r - l) {
      int L = l | ((1U << 31) >> __builtin_clz(d));
      int k = __builtin_ctz(L);
      x = f(x, seg[(sz | l) >> k]);
      l += L & (-L);
    }
    return x;
  }
  void update(int i, T x) {
    int k = i + sz;
    seg[k] = x;
    for (k = k >> 1; k > 0; k >>= 1) {
      seg[k] = f(seg[k << 1], seg[(k << 1) | 1]);
    }
  }
  void add(int i, T x) {
    int k = i + sz;
    seg[k] += x;
    for (k = k >> 1; k > 0; k >>= 1) {
      seg[k] = f(seg[k << 1], seg[(k << 1) | 1]);
    }
  }
  SegmentTree() = default;
  T operator[](int k) const { return seg[sz + k]; }
};
template <typename T>
struct RMQ : SegmentTree<T> {
  RMQ(int n)
      : SegmentTree<T>(
            n, [](T i, T j) { return max(i, j); }, numeric_limits<T>::min()) {}
  RMQ(vector<T> &a)
      : SegmentTree<T>(
            a, [](T i, T j) { return max(i, j); }, numeric_limits<T>::min()) {}
};
template <typename T>
struct RmQ : SegmentTree<T> {
  RmQ(int n)
      : SegmentTree<T>(
            n, [](T i, T j) { return min(i, j); }, numeric_limits<T>::max()) {}
  RmQ(vector<T> &a)
      : SegmentTree<T>(
            a, [](T i, T j) { return min(i, j); }, numeric_limits<T>::max()) {}
};
template <typename T>
struct RAQ : SegmentTree<T> {
  RAQ(int n) : SegmentTree<T>(n, plus<T>(), 0) {}
  RAQ(vector<T> &a) : SegmentTree<T>(a, plus<T>(), 0) {}
};
int main() {
  int n, k;
  IN(n, k);
  vector<int> a(n);
  IN(a);
  const int N = 300001;
  RMQ<int> seg(N);
  for (long long i = 0; i < n; ++i) seg.set(i, 0);
  seg.build();
  for (long long i = 0; i < n; ++i) {
    seg.update(a[i], seg.query(max(0, a[i] - k), min(N, a[i] + k + 1)) + 1);
  }
  cout << seg.query(0, N) << '\n';
}
