#include <algorithm>
#include <complex>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string.h>
#include <string>
#include <time.h>
#include <vector>
using namespace std;
#define rep(i, a, n) for (llint i = (a); i < (n); i++)
#define ll long long
#define llint long long int
#define reverse(v) reverse(v.begin(), v.end());
#define Yes(ans)                                                               \\
  if (ans)                                                                     \\
    cout << "Yes" << endl;                                                     \\
  else                                                                         \\
    cout << "No" << endl;
#define YES(ans)                                                               \\
  if (ans)                                                                     \\
    cout << "YES" << endl;                                                     \\
  else                                                                         \\
    cout << "NO" << endl;
#define hei(a) vector<a>
#define whei(a) vector<vector<a>>
#define UF UnionFind
#define Pint pair<int, int>
#define Pll pair<llint, llint>
#define keta(a) fixed << setprecision(a)
const ll mod = 1000000007;
// 辞書順はnext_permutation( begin( v ), end( v ) );やで！
const ll INF = 1000000000;

class UnionFind {
public:
  // 親の番号を格納する
  vector<int> par;

  // 最初は全てが根であるとして初期化
  UnionFind(int N) {
    par.resize(N);
    for (int i = 0; i < N; i++)
      par[i] = i;
  }

  // Aがどのグループに属しているか調べる
  int root(int A) {
    if (par[A] == A)
      return A;
    return par[A] = root(par[A]);
  }

  // AとBをくっ付ける
  bool unite(int A, int B) {
    // AとBを直接つなぐのではなく、root(A)にroot(B)をくっつける
    A = root(A);
    B = root(B);
    if (A == B) {
      // すでにくっついてるからくっ付けない
      return false;
    }

    // Bの親をAに変更する
    par[B] = A;

    return true;
  }
  bool same(int x, int y) { // 2つのデータx, yが属する木が同じならtrueを返す
    int rx = root(x);
    int ry = root(y);
    return rx == ry;
  }
};

int main() {
  int n, k;
  cin >> n >> k;
  hei(int) a(n);
  rep(i, 0, n) cin >> a[i];
  hei(int) dp(n, 1);
  rep(i, 0, n) {
    rep(j, i + 1, n) {
      if (abs(a[i] - a[j]) <= k) {
        dp[j] = max(dp[i] + 1, dp[j]);
      }
    }
  }
  cout << dp[n - 1] << endl;
  return 0;
}

#include <algorithm>
#include <complex>
#include <functional>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string.h>
#include <string>
#include <time.h>
#include <vector>
using namespace std;
#define rep(i, a, n) for (llint i = (a); i < (n); i++)
#define ll long long
#define llint long long int
#define reverse(v) reverse(v.begin(), v.end());
#define Yes(ans)                                                               \\
  if (ans)                                                                     \\
    cout << "Yes" << endl;                                                     \\
  else                                                                         \\
    cout << "No" << endl;
#define YES(ans)                                                               \\
  if (ans)                                                                     \\
    cout << "YES" << endl;                                                     \\
  else                                                                         \\
    cout << "NO" << endl;
#define hei(a) vector<a>
#define whei(a) vector<vector<a>>
#define UF UnionFind
#define Pint pair<int, int>
#define Pll pair<llint, llint>
#define keta(a) fixed << setprecision(a)
const ll mod = 1000000007;
// 辞書順はnext_permutation( begin( v ), end( v ) );やで！
const ll INF = 1000000000;

class UnionFind {
public:
  // 親の番号を格納する
  vector<int> par;

  // 最初は全てが根であるとして初期化
  UnionFind(int N) {
    par.resize(N);
    for (int i = 0; i < N; i++)
      par[i] = i;
  }

  // Aがどのグループに属しているか調べる
  int root(int A) {
    if (par[A] == A)
      return A;
    return par[A] = root(par[A]);
  }

  // AとBをくっ付ける
  bool unite(int A, int B) {
    // AとBを直接つなぐのではなく、root(A)にroot(B)をくっつける
    A = root(A);
    B = root(B);
    if (A == B) {
      // すでにくっついてるからくっ付けない
      return false;
    }

    // Bの親をAに変更する
    par[B] = A;

    return true;
  }
  bool same(int x, int y) { // 2つのデータx, yが属する木が同じならtrueを返す
    int rx = root(x);
    int ry = root(y);
    return rx == ry;
  }
};

template <class T> class SegTree {
public:
  int size;
  vector<T> seg;                             // 配列
  T e;                                       // 単位元
  function<T(T, T)> f;                       // 演算
  SegTree(T n, T _e, function<T(T, T)> _f) { // コンストラクタ(初期化)
    f = _f;
    e = _e;
    size = 1;
    while (size < n)
      size *= 2;
    seg.resize(size * 2 - 1, e);
  }

  void updata(int n, int k) { // 一点更新
    n += size - 1;
    seg[n] = k;
    while (n > 0) {
      n = (n - 1) / 2;
      seg[n] = f(seg[n * 2 + 1], seg[n * 2 + 2]);
    }
  }
  T query(int a, int b, int l, int r, int k) {
    if (b <= l || r <= a)
      return e;
    if (a <= l && r <= b)
      return seg[k];
    T v1 = query(a, b, l, (l + r) / 2, k * 2 + 1);
    T v2 = query(a, b, (l + r) / 2, r, k * 2 + 2);
    return f(v1, v2);
  }
};

int main() {
  int n, k;
  cin >> n >> k;
  SegTree<int> tree(300001, 0, [](int a, int b) { return max(a, b); });
  hei(int) a(n);
  rep(i, 0, n) { cin >> a[i]; }
  int ans = 0;
  rep(i, 0, n) {
    int l = max(0, a[i] - k);
    int r = min(a[i] + k, tree.size);
    int sum = tree.query(l, r + 1, 0, tree.size, 0) + 1;
    ans = max(ans, sum);
    tree.updata(a[i], sum);
  }
  cout << ans << endl;
  return 0;
}


#include <bits/stdc++.h>
using namespace std;

#define ll long long int
#define pb push_back
#define FastIO cin.sync_with_stdio(false), cin.tie(NULL)
#define file                                                                   \\
  freopen("input.txt", "r", stdin), freopen("output.txt", "w", stdout)

ll max(ll a, ll b) {
  if (a > b)
    return a;
  return b;
}

ll min(ll a, ll b) {
  if (a < b)
    return a;
  return b;
}

ll ceil_div(ll a, ll b) { return (a + b - 1) / b; }

const ll N = 3e5 + 5, INF = 2e9 + 2, MOD = 998244353, M = 6000, K = 20;
int a[2 * N], segment[4 * N], b[N];

void build(int ind, int l, int r) {
  if (r == l)
    return;
  if (r - l == 1) {
    segment[ind] = a[l];
    return;
  }
  int mid = (l + r) / 2;
  build(ind * 2, l, mid);
  build(ind * 2 + 1, mid, r);
  segment[ind] = max(segment[2 * ind], segment[2 * ind + 1]);
}

void update(int ind, int l, int r, int i, int v) {
  int mid = (l + r) / 2;
  if (r - l == 1) {
    segment[ind] = v;
    return;
  }
  if (i < mid)
    update(2 * ind, l, mid, i, v);
  else
    update(2 * ind + 1, mid, r, i, v);
  segment[ind] = max(segment[2 * ind], segment[2 * ind + 1]);
}

int ql, qr;
ll query(int ind, int l, int r) {
  int mid = (l + r) / 2;
  if (l >= ql && r <= qr)
    return segment[ind];
  if (r <= ql || l >= qr)
    return 0;
  ll ans = 0;
  ans = max(query(2 * ind, l, mid), query(2 * ind + 1, mid, r));
  return ans;
}

int main() {
  FastIO;
  int n, k;
  cin >> n >> k;
  for (int i = 0; i < n; i++)
    cin >> b[i];
  a[b[0]] = 1;
  build(1, 0, 2 * N);

  ll tp;
  for (int i = 1; i < n; i++) {
    ql = max(0, b[i] - k);
    qr = min(2 * N, b[i] + k + 1);
    tp = query(1, 0, 2 * N);
    a[b[i]] = tp + 1;
    update(1, 0, 2 * N, b[i], tp + 1);
  }

  cout << max(segment[1], *max_element(a, a + N)) << "\\n";

  return 0;
}

#include <bits/stdc++.h>
using namespace std;

#define ll long long int
#define pb push_back
#define FastIO cin.sync_with_stdio(false), cin.tie(NULL)
#define file                                                                   \\
  freopen("input.txt", "r", stdin), freopen("output.txt", "w", stdout)

ll max(ll a, ll b) {
  if (a > b)
    return a;
  return b;
}

ll min(ll a, ll b) {
  if (a < b)
    return a;
  return b;
}

ll ceil_div(ll a, ll b) { return (a + b - 1) / b; }

const ll N = 3e5 + 5, INF = 2e9 + 2, MOD = 998244353, M = 6000, K = 20;
int a[N], segment[3 * N], b[N];

void build(int ind, int l, int r) {
  if (r <= l)
    return;
  if (r - l == 1) {
    segment[ind] = a[l];
    return;
  }
  int mid = (l + r) / 2;
  build(2 * ind, l, mid);
  build(2 * ind + 1, mid, r);
  segment[ind] = max(segment[2 * ind], segment[2 * ind + 1]);
}

void update(int ind, int l, int r, int i, int v) {
  int mid = (l + r) / 2;
  if (r - l == 1) {
    segment[ind] = v;
    return;
  }
  if (i < mid)
    update(2 * ind, l, mid, i, v);
  else
    update(2 * ind + 1, mid, r, i, v);
  segment[ind] = max(segment[2 * ind], segment[2 * ind + 1]);
}

int ql, qr;
ll query(int ind, int l, int r) {
  int mid = (l + r) / 2;
  if (l >= ql && r <= qr)
    return segment[ind];
  if (r <= ql || l >= qr || r <= l)
    return 0;
  ll ans = 0;
  ans = max(query(2 * ind, l, mid), query(2 * ind + 1, mid, r));
  return ans;
}

int main() {
  // FastIO;
  int n, k;
  cin >> n >> k;
  for (int i = 0; i < n; i++)
    cin >> b[i];
  a[b[0]] = 1;
  if (n == 1) {
    cout << 1 << "\\n";
    return 0;
  }
  build(1, 0, N);

  ll tp;
  for (int i = 1; i < n; i++) {
    ql = max(0, b[i] - k);
    qr = min(N, b[i] + k + 1);
    tp = query(1, 0, N);
    a[b[i]] = tp + 1;
    update(1, 0, N, b[i], tp + 1);
  }

  cout << segment[1] << "\\n";

  return 0;
}


#include <bits/stdc++.h>

#define _GLIBCXX_DEBUG
#define all(v) (v).begin(), (v).end()

using namespace std;

using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using vi = vector<int>;
using vii = vector<vector<int>>;

const ll LINF = 1LL << 60;
const int INF = 1 << 29;
const int MOD = 1e9 + 7;

template <typename T> bool chmin(T &a, const T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <typename T> bool chmax(T &a, const T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

int main() {
  int N, K;
  cin >> N >> K;
  vi A(N);
  for (int i = 0; i < N; i++) {
    cin >> A[i];
  }

  vi dp(N, 1);
  int ans = 0;
  for (int i = 0; i < N; i++) {
    for (int j = 0; j < i; j++) {
      if (abs(A[i] - A[j]) <= K)
        chmax(dp[i], dp[j] + 1);
    }
    chmax(ans, dp[i]);
  }
  cout << ans << endl;
  return 0;
}

#include <bits/stdc++.h>

#define _GLIBCXX_DEBUG
#define all(v) (v).begin(), (v).end()

using namespace std;

using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using vi = vector<int>;
using vii = vector<vector<int>>;

const ll LINF = 1LL << 60;
const int INF = 1 << 29;
const int MOD = 1e9 + 7;

template <typename T> bool chmin(T &a, const T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <typename T> bool chmax(T &a, const T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

int n_;
vector<int> dat;

void init(int size) {
  // initialize size=a power of 2
  n_ = 1;
  while (n_ < size)
    n_ *= 2;
  dat.assign(2 * n_ - 1, 0);
}

// a_id(0-indexed) -> val
void update(int id, int val) {
  // id of leaf
  id += n_ - 1;
  dat[id] = val;
  while (id > 0) {
    id = (id - 1) / 2;
    dat[id] = max(dat[2 * id + 1], dat[2 * id + 2]);
  }
}

// get Min{a_i | s <= i < t}, [s, t)
// dat[id] interval -> [l, r)
// first, query(s, t, 0, 0, n_)
int query(int s, int t, int id, int l, int r) {
  if (r <= s || t <= l)
    return 0;

  if (s <= l && r <= t)
    return dat[id];
  int vl = query(s, t, 2 * id + 1, l, (l + r) / 2);
  int vr = query(s, t, 2 * id + 2, (l + r) / 2, r);
  return max(vl, vr);
}

int main() {
  int N, K;
  cin >> N >> K;
  vi A(N);
  int mx = 0;
  for (int i = 0; i < N; i++) {
    cin >> A[i];
    chmax(mx, A[i]);
  }
  vi nA = A;
  sort(all(nA));

  init(mx + 1);
  for (int i = 0; i < N; i++) {
    int id1 = lower_bound(all(nA), A[i] - K) - nA.begin();
    int id2 = upper_bound(all(nA), A[i] + K) - nA.begin();
    update(A[i], query(nA[id1], nA[id2 - 1] + 1, 0, 0, n_) + 1);
  }
  cout << query(0, n_, 0, 0, n_) << endl;
  return 0;
}


#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); i++)
using namespace std;
using ll = long long;
using P = pair<int, int>;

template <class Monoid> struct SegTree {
  using Func = function<Monoid(Monoid, Monoid)>;
  const Func F;
  const Monoid UNITY;
  int SIZE_R;
  vector<Monoid> dat;

  SegTree(int n, const Func f, const Monoid &unity) : F(f), UNITY(unity) {
    init(n);
  }
  void init(int n) {
    SIZE_R = 1;
    while (SIZE_R < n)
      SIZE_R *= 2;
    dat.assign(SIZE_R * 2, UNITY);
  }

  /* set, a is 0-indexed */
  void set(int a, const Monoid &v) { dat[a + SIZE_R] = v; }
  void build() {
    for (int k = SIZE_R - 1; k > 0; k--) {
      dat[k] = F(dat[k * 2], dat[k * 2 + 1]);
    }
  }

  /*update a, a is 0-indexed */
  void update(int a, const Monoid &v) {
    int k = a + SIZE_R;
    dat[k] = v;
    while (k >>= 1)
      dat[k] = F(dat[k * 2], dat[k * 2 + 1]);
  }

  /* get [a, b), a and b are 0-indexed */
  Monoid get(int a, int b) {
    Monoid vleft = UNITY, vright = UNITY;
    for (int left = a + SIZE_R, right = b + SIZE_R; left < right;
         left >>= 1, right >= 1) {
      if (left & 1)
        vleft = F(vleft, dat[left++]);
      if (right & 1)
        vright = F(dat[--right], vright);
    }
    return F(vleft, vright);
  }
  inline Monoid operator[](int a) { return dat[a + SIZE_R]; }

  /* debug */
  void print() {
    for (int i = 0; i < SIZE_R; i++) {
      cout << (*this)[i];
      if (i != SIZE_R - 1)
        cout << ",";
    }
    cout << endl;
  }
};

int solve(int N, int K) {
  const int MAX = 510000;
  auto func = [&](int a, int b) { return max(a, b); };
  SegTree<int> seg(MAX, func, 0);
  for (int i = 0; i < N; i++) {
    int a;
    cin >> a;
    int left = max(0, a - K);
    int right = min(MAX, a + K + 1);
    int val = seg.get(left, right);
    seg.update(a, val + 1);
  }
  return seg.get(0, MAX);
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int n, k;
  cin >> n >> k;
  cout << solve(n, k) << endl;
}

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); i++)
using namespace std;
using ll = long long;
using P = pair<int, int>;

template <class Monoid> struct SegTree {
  using Func = function<Monoid(Monoid, Monoid)>;
  const Func F;
  const Monoid UNITY;
  int SIZE_R;
  vector<Monoid> dat;

  SegTree(int n, const Func f, const Monoid &unity) : F(f), UNITY(unity) {
    init(n);
  }
  void init(int n) {
    SIZE_R = 1;
    while (SIZE_R < n)
      SIZE_R *= 2;
    dat.assign(SIZE_R * 2, UNITY);
  }

  /* set, a is 0-indexed */
  void set(int a, const Monoid &v) { dat[a + SIZE_R] = v; }
  void build() {
    for (int k = SIZE_R - 1; k > 0; --k)
      dat[k] = F(dat[k * 2], dat[k * 2 + 1]);
  }

  /* update a, a is 0-indexed */
  void update(int a, const Monoid &v) {
    int k = a + SIZE_R;
    dat[k] = v;
    while (k >>= 1)
      dat[k] = F(dat[k * 2], dat[k * 2 + 1]);
  }

  /* get [a, b), a and b are 0-indexed */
  Monoid get(int a, int b) {
    Monoid vleft = UNITY, vright = UNITY;
    for (int left = a + SIZE_R, right = b + SIZE_R; left < right;
         left >>= 1, right >>= 1) {
      if (left & 1)
        vleft = F(vleft, dat[left++]);
      if (right & 1)
        vright = F(dat[--right], vright);
    }
    return F(vleft, vright);
  }
  inline Monoid operator[](int a) { return dat[a + SIZE_R]; }

  /* debug */
  void print() {
    for (int i = 0; i < SIZE_R; ++i) {
      cout << (*this)[i];
      if (i != SIZE_R - 1)
        cout << ",";
    }
    cout << endl;
  }
};

int solve(int N, int K) {
  const int MAX = 510000;
  auto func = [&](int a, int b) { return max(a, b); };
  SegTree<int> seg(MAX, func, 0);
  for (int i = 0; i < N; i++) {
    int a;
    cin >> a;
    int left = max(0, a - K);
    int right = min(MAX, a + K + 1);
    int val = seg.get(left, right);
    seg.update(a, val + 1);
  }
  return seg.get(0, MAX);
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int n, k;
  cin >> n >> k;
  cout << solve(n, k) << endl;
}


// D - Flat Subsequence
#include <bits/stdc++.h>
using namespace std;
#define rp(i, s, e) for (int i = (int)(s); i < (int)(e); ++i)
#define chmax(x, y) x = max(x, (y))

#define MAX 300'005
int dp[MAX];

int main() {
  int n, k;
  cin >> n >> k;
  int ans = 0;
  rp(i, 0, n) {
    int ai;
    cin >> ai;
    int longest = 0;
    int l = max(0, ai - k);
    int r = min(ai + k + 1, MAX);
    rp(aj, l, r) chmax(longest, dp[aj]); // [l,r)
    chmax(dp[ai], longest + 1);
    chmax(ans, dp[ai]);
  }
  cout << ans << endl;
}

// D - Flat Subsequence
#include <bits/stdc++.h>
using namespace std;

#include <atcoder/segtree>
int op(int a, int b) { return max(a, b); } // 処理
int e() { return 0; }                      // 単位元
using MONOID = int;
using SEG_T = atcoder::segtree<MONOID, op, e>;
#define SEGT_MAX 300005

int main() {
  int n, k;
  cin >> n >> k;
  vector<int> A(n);
  for (auto &a : A)
    cin >> a;
  SEG_T seg(SEGT_MAX);
  int ans = 0;
  for (int &a : A) {
    int l = max(0, a - k);
    int r = min(a + k + 1, SEGT_MAX);
    int longest = seg.prod(l, r); // [l,r)
    seg.set(a, longest + 1);
    ans = max(ans, longest + 1);
  }
  cout << ans << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define all(a) a.begin(), a.end()
using ll = long long;
const int INF = 1 << 30;
const ll INFll = 1LL << 62;
const int mod = int(1e9) + 7;
// const int mod=998244353;
using P = pair<int, int>;
using Pl = pair<ll, ll>;
using ld = long double;
using V = vector<int>;
using Vl = vector<ll>;
using VV = vector<vector<int>>;
using VVl = vector<vector<ll>>;

int MAX_N = 300001;
VVl bit(MAX_N, Vl()); // 1-index
void add(ll i, ll a, ll w) {
  for (ll x = a; x <= MAX_N; x += x & -x)
    bit[x][i] += w;
}
ll sum(ll i, ll a) { // sum v[1]～v[a]
  ll ret = 0;
  for (int x = a; x > 0; x -= x & -x)
    ret += bit[x][i];
  return ret;
}

int main() {
  ll n, k;
  cin >> n >> k;
  Vl a(n);
  for (int i = 0; i < n; ++i) {
    cin >> a[i];
  }
  ll mm = 0;
  Vl tp(MAX_N, 0);
  for (ll i = 0; i < n; ++i) {
    for (ll j = mm; j >= 0; --j) {
      //            cout <<a[i]<<" "<<j<<endl;
      if (j == 0) {
        if (bit.size() == j) {
          bit.push_back(tp);
        }
        if (a[i] + k + 1 <= MAX_N) {
          add(j + 1, a[i] + k + 1, -1);
        }
        if (a[i] - k >= 0) {
          add(j + 1, a[i] - k, 1);
        }
        mm = max(mm, j + 1);
        //                cout <<j+1<<" "<<a[i]<<endl;
      } else {

        if (sum(j, a[i])) {
          if (bit.size() == j) {
            bit.push_back(tp);
          }
          if (a[i] + k + 1 <= MAX_N) {
            add(j + 1, a[i] + k + 1, -1);
          }
          if (a[i] - k >= 0) {
            add(j + 1, a[i] - k, 1);
          }
          mm = max(mm, j + 1);
        }
      }
    }
  }
  cout << mm << endl;
}

#include <atcoder/segtree>
#include <bits/stdc++.h>
using namespace std;
#define all(a) a.begin(), a.end()
using ll = long long;
const int INF = 1 << 30;
const ll INFll = 1LL << 62;
const int mod = int(1e9) + 7;
// const int mod=998244353;
using P = pair<int, int>;
using Pl = pair<ll, ll>;
using ld = long double;
using V = vector<int>;
using Vl = vector<ll>;
using VV = vector<vector<int>>;
using VVl = vector<vector<ll>>;

int op(int a, int b) { return max(a, b); }
int e() { return 0; }

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int n, k;
  cin >> n >> k;
  V a(n);
  for (int i = 0; i < n; ++i) {
    cin >> a[i];
  }
  const int MAX_A = 300101;
  atcoder::segtree<int, op, e> dp(MAX_A);
  for (int i = 0; i < n; ++i) {
    int l, r;
    l = a[i] - k;
    r = a[i] + k + 1;
    l = max(0, l);
    r = min(MAX_A, r);
    int now = dp.prod(l, r);
    dp.set(a[i], now + 1);
  }
  cout << dp.all_prod() << "\\n";
}


#include <bits/stdc++.h>

#define fast                                                                   \\
  ios::sync_with_stdio(false);                                                 \\
  cin.tie(NULL);                                                               \\
  cout.tie(NULL)
#define int long long
#define endl '\\n'

using namespace std;

const int N = 3e5 + 77;
int A[N], dp[N];

int32_t main() {
  fast;
  int n, k;
  cin >> n >> k;
  for (int i = 0; i < n; ++i) {
    cin >> A[i];
  }
  int ans = 0;
  dp[0] = 1;
  for (int i = 1; i < n; ++i) {
    for (int j = 0; j < i; ++j) {
      if (abs(A[i] - A[j]) <= k)
        dp[i] = max(dp[i], dp[j] + 1);
    }
  }
  for (int i = 0; i < n; ++i)
    ans = max(dp[i], ans);
  // for(int i = 0; i < n ; ++i) cout << dp[i] << ' ' ; cout << endl;
  cout << ans << endl;
  return 0;
}

#include <bits/stdc++.h>

#define fast                                                                   \\
  ios::sync_with_stdio(false);                                                 \\
  cin.tie(NULL);                                                               \\
  cout.tie(NULL)
#define int long long
#define endl '\\n'

using namespace std;

const int N = 3e5 + 77;
int A[N], dp[N];

int32_t main() {
  fast;
  int n, k;
  cin >> n >> k;
  for (int i = 1; i <= n; ++i) {
    cin >> A[i];
  }
  for (int i = 1; i <= n; ++i) {
    dp[i] = 1;
    for (int j = i - 1; i - j <= 100 && j >= 1; --j)
      if (abs(A[i] - A[j]) <= k)
        dp[i] = max(dp[i], dp[j] + 1);
  }
  int ans = 0;
  // for(int i = 1 ; i <= n ; ++i) cout << dp[i] << ' ' ; cout << endl;
  for (int i = 1; i <= n; ++i)
    ans = max(ans, dp[i]);
  cout << ans << endl;
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define REP(i, x, n) for (int i = x; i < (int)n; i++)
#define rep(i, n) REP(i, 0, n)
#define sp(p) cout << setprecision(16) << fixed << p << endl;
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define SORT(a) sort(all(a))
#define RSORT(a) sort(rall(a))
#define UNIQ(a) unique(all(a))
#define UNIQNUM(a) UNIQ(a) - a.begin()
#define UNIQIT(a) a.erase(UNIQ(a), a.end());
#define VOUT(v, i)                                                             \\
  rep(i, v.size()) cout << v[i] << (i == v.size() - 1 ? "\\n" : " ");
#define vout(v) VOUT(v, z);
#define vdbg(v, i)                                                             \\
  cout << #v << ": ";                                                          \\
  for (int i = 0; i < (int)v.size(); i++) {                                    \\
    cout << v[i] << " ";                                                       \\
  }                                                                            \\
  cout << "\\n";
#define vmin(v) *min_element(all(v))
#define vmax(v) *max_element(all(v))
#define vsum(v) accumulate(all(v), 0LL)
#define MOUT(m, r, c)                                                          \\
  rep(i, r) {                                                                  \\
    rep(j, c) { cout << m[i][j] << " "; }                                      \\
    cout << endl;                                                              \\
  }
#define mout(m) MOUT(m, m.size(), m[0].size())
#define debg(a) cout << #a << ": " << a << endl;
#define out(a) debg(a);
#define aout(a)                                                                \\
  for (auto &e : a)                                                            \\
    cout << e << " ";
#define show(a)                                                                \\
  for (cont & y : a) {                                                         \\
    for (cont & x : y) {                                                       \\
      cout << x << " ";                                                        \\
    }                                                                          \\
    cout << endl;                                                              \\
  }
#define digit(a) to_string(a).length();
// template<class T>inline int out(const T &t){ print(t); putchar('\\n'); return
// 0; } template<class T>inline T gcd(T a,T b){if(b==0)return a;
// return(gcd(b,a%b));} template<class T>inline T lcm(T a,T b){return
// a/gcd(a,b)*b;}
bool is_palindrome(string s) { return s == string(s.rbegin(), s.rend()); }
#define popcount __builtin_popcount
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> P;
typedef vector<ll> V;
typedef vector<vector<ll>> VV;
// const long long MOD=1000000007;
const long long INF = 1e18;
#define EPS (1e-7)
#define PI (acos(-1))
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}

namespace internal {

template <class E> struct csr {
  std::vector<int> start;
  std::vector<E> elist;
  csr(int n, const std::vector<std::pair<int, E>> &edges)
      : start(n + 1), elist(edges.size()) {
    for (auto e : edges) {
      start[e.first + 1]++;
    }
    for (int i = 1; i <= n; i++) {
      start[i] += start[i - 1];
    }
    auto counter = start;
    for (auto e : edges) {
      elist[counter[e.first]++] = e.second;
    }
  }
};

// Reference:
// R. Tarjan,
// Depth-First Search and Linear Graph Algorithms
struct scc_graph {
public:
  scc_graph(int n) : _n(n) {}

  int num_vertices() { return _n; }

  void add_edge(int from, int to) { edges.push_back({from, {to}}); }

  // @return pair of (# of scc, scc id)
  std::pair<int, std::vector<int>> scc_ids() {
    auto g = csr<edge>(_n, edges);
    int now_ord = 0, group_num = 0;
    std::vector<int> visited, low(_n), ord(_n, -1), ids(_n);
    visited.reserve(_n);
    auto dfs = [&](auto self, int v) -> void {
      low[v] = ord[v] = now_ord++;
      visited.push_back(v);
      for (int i = g.start[v]; i < g.start[v + 1]; i++) {
        auto to = g.elist[i].to;
        if (ord[to] == -1) {
          self(self, to);
          low[v] = std::min(low[v], low[to]);
        } else {
          low[v] = std::min(low[v], ord[to]);
        }
      }
      if (low[v] == ord[v]) {
        while (true) {
          int u = visited.back();
          visited.pop_back();
          ord[u] = _n;
          ids[u] = group_num;
          if (u == v)
            break;
        }
        group_num++;
      }
    };
    for (int i = 0; i < _n; i++) {
      if (ord[i] == -1)
        dfs(dfs, i);
    }
    for (auto &x : ids) {
      x = group_num - 1 - x;
    }
    return {group_num, ids};
  }

  std::vector<std::vector<int>> scc() {
    auto ids = scc_ids();
    int group_num = ids.first;
    std::vector<int> counts(group_num);
    for (auto x : ids.second)
      counts[x]++;
    std::vector<std::vector<int>> groups(ids.first);
    for (int i = 0; i < group_num; i++) {
      groups[i].reserve(counts[i]);
    }
    for (int i = 0; i < _n; i++) {
      groups[ids.second[i]].push_back(i);
    }
    return groups;
  }

private:
  int _n;
  struct edge {
    int to;
  };
  std::vector<std::pair<int, edge>> edges;
};

} // namespace internal

struct two_sat {
public:
  two_sat() : _n(0), scc(0) {}
  two_sat(int n) : _n(n), _answer(n), scc(2 * n) {}

  void add_clause(int i, bool f, int j, bool g) {
    assert(0 <= i && i < _n);
    assert(0 <= j && j < _n);
    scc.add_edge(2 * i + (f ? 0 : 1), 2 * j + (g ? 1 : 0));
    scc.add_edge(2 * j + (g ? 0 : 1), 2 * i + (f ? 1 : 0));
  }
  bool satisfiable() {
    auto id = scc.scc_ids().second;
    for (int i = 0; i < _n; i++) {
      if (id[2 * i] == id[2 * i + 1])
        return false;
      _answer[i] = id[2 * i] < id[2 * i + 1];
    }
    return true;
  }
  std::vector<bool> answer() { return _answer; }

private:
  int _n;
  std::vector<bool> _answer;
  internal::scc_graph scc;
};

int main() {
  long long N;
  scanf("%lld", &N);
  long long K;
  scanf("%lld", &K);
  std::vector<long long> A(N);
  for (int i = 0; i < N; i++) {
    scanf("%lld", &A[i]);
  }
  two_sat ts(N);
  for (int i = 0; i < N; i++) {
    for (int j = i + 1; j < N; j++) {
      if (abs(A[i] - A[j]) < K) {
        ts.add_clause(i, true, j, true);
      }
    }
  }
  ts.satisfiable();
  // out(ts.satisfiable());
  // vout(ts.answer());
  vector<bool> v = ts.answer();
  // int cnt=0;
  // for (long long i = 0; i < N; i++) {
  //     if(v[i]) cnt++;
  // }
  int ret = vsum(v);
  cout << ret << endl;
  return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define REP(i, x, n) for (int i = x; i < (int)n; i++)
#define rep(i, n) REP(i, 0, n)
#define sp(p) cout << setprecision(16) << fixed << p << endl;
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define SORT(a) sort(all(a))
#define RSORT(a) sort(rall(a))
#define UNIQ(a) unique(all(a))
#define UNIQNUM(a) UNIQ(a) - a.begin()
#define UNIQIT(a) a.erase(UNIQ(a), a.end());
#define VOUT(v, i)                                                             \\
  rep(i, v.size()) cout << v[i] << (i == v.size() - 1 ? "\\n" : " ");
#define vout(v) VOUT(v, z);
#define vdbg(v, i)                                                             \\
  cout << #v << ": ";                                                          \\
  for (int i = 0; i < (int)v.size(); i++) {                                    \\
    cout << v[i] << " ";                                                       \\
  }                                                                            \\
  cout << "\\n";
#define vmin(v) *min_element(all(v))
#define vmax(v) *max_element(all(v))
#define vsum(v) accumulate(all(v), 0LL)
#define MOUT(m, r, c)                                                          \\
  rep(i, r) {                                                                  \\
    rep(j, c) { cout << m[i][j] << " "; }                                      \\
    cout << endl;                                                              \\
  }
#define mout(m) MOUT(m, m.size(), m[0].size())
#define debg(a) cout << #a << ": " << a << endl;
#define out(a) debg(a);
#define aout(a)                                                                \\
  for (auto &e : a)                                                            \\
    cout << e << " ";
#define show(a)                                                                \\
  for (cont & y : a) {                                                         \\
    for (cont & x : y) {                                                       \\
      cout << x << " ";                                                        \\
    }                                                                          \\
    cout << endl;                                                              \\
  }
#define digit(a) to_string(a).length();
// template<class T>inline int out(const T &t){ print(t); putchar('\\n'); return
// 0; } template<class T>inline T gcd(T a,T b){if(b==0)return a;
// return(gcd(b,a%b));} template<class T>inline T lcm(T a,T b){return
// a/gcd(a,b)*b;}
bool is_palindrome(string s) { return s == string(s.rbegin(), s.rend()); }
#define popcount __builtin_popcount
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> P;
typedef vector<ll> V;
typedef vector<vector<ll>> VV;
// const long long MOD=1000000007;
const long long INF = 1e18;
#define EPS (1e-7)
#define PI (acos(-1))
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}

namespace internal {

// @param n `0 <= n`
// @return minimum non-negative `x` s.t. `n <= 2**x`
int ceil_pow2(int n) {
  int x = 0;
  while ((1U << x) < (unsigned int)(n))
    x++;
  return x;
}

// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
int bsf(unsigned int n) {
#ifdef _MSC_VER
  unsigned long index;
  _BitScanForward(&index, n);
  return index;
#else
  return __builtin_ctz(n);
#endif
}

} // namespace internal

template <class S, S (*op)(S, S), S (*e)()> struct segtree {
public:
  segtree() : segtree(0) {}
  segtree(int n) : segtree(std::vector<S>(n, e())) {}
  segtree(const std::vector<S> &v) : _n(int(v.size())) {
    log = internal::ceil_pow2(_n);
    size = 1 << log;
    d = std::vector<S>(2 * size, e());
    for (int i = 0; i < _n; i++)
      d[size + i] = v[i];
    for (int i = size - 1; i >= 1; i--) {
      update(i);
    }
  }

  void set(int p, S x) {
    assert(0 <= p && p < _n);
    p += size;
    d[p] = x;
    for (int i = 1; i <= log; i++)
      update(p >> i);
  }

  S get(int p) {
    assert(0 <= p && p < _n);
    return d[p + size];
  }

  S prod(int l, int r) {
    assert(0 <= l && l <= r && r <= _n);
    S sml = e(), smr = e();
    l += size;
    r += size;

    while (l < r) {
      if (l & 1)
        sml = op(sml, d[l++]);
      if (r & 1)
        smr = op(d[--r], smr);
      l >>= 1;
      r >>= 1;
    }
    return op(sml, smr);
  }

  S all_prod() { return d[1]; }

  template <bool (*f)(S)> int max_right(int l) {
    return max_right(l, [](S x) { return f(x); });
  }
  template <class F> int max_right(int l, F f) {
    assert(0 <= l && l <= _n);
    assert(f(e()));
    if (l == _n)
      return _n;
    l += size;
    S sm = e();
    do {
      while (l % 2 == 0)
        l >>= 1;
      if (!f(op(sm, d[l]))) {
        while (l < size) {
          l = (2 * l);
          if (f(op(sm, d[l]))) {
            sm = op(sm, d[l]);
            l++;
          }
        }
        return l - size;
      }
      sm = op(sm, d[l]);
      l++;
    } while ((l & -l) != l);
    return _n;
  }

  template <bool (*f)(S)> int min_left(int r) {
    return min_left(r, [](S x) { return f(x); });
  }
  template <class F> int min_left(int r, F f) {
    assert(0 <= r && r <= _n);
    assert(f(e()));
    if (r == 0)
      return 0;
    r += size;
    S sm = e();
    do {
      r--;
      while (r > 1 && (r % 2))
        r >>= 1;
      if (!f(op(d[r], sm))) {
        while (r < size) {
          r = (2 * r + 1);
          if (f(op(d[r], sm))) {
            sm = op(d[r], sm);
            r--;
          }
        }
        return r + 1 - size;
      }
      sm = op(d[r], sm);
    } while ((r & -r) != r);
    return 0;
  }

private:
  int _n, size, log;
  std::vector<S> d;

  void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
};

int max_op(int a, int b) { return max(a, b); };
int e() { return 0; };

int main() {
  long long N;
  scanf("%lld", &N);
  long long K;
  scanf("%lld", &K);
  std::vector<long long> A(N);
  for (int i = 0; i < N; i++) {
    scanf("%lld", &A[i]);
  }
  segtree<int, max_op, e> st(3e6 + 1);
  int ans = 0;
  for (long long i = 0; i < N; i++) {
    int l = max(A[i] - K, 0LL);
    int r = max(A[i] + K + 1, 0LL);
    int tmp = 1 + st.prod(l, r);
    st.set(A[i], max(st.get(A[i]), tmp));
    ans = max(ans, tmp);
  }
  cout << ans << endl;
  return 0;
}


#include <bits/stdc++.h>
#define rep(i, a, b) for (ll i = ll(a); i < ll(b); i++)
#define irep(i, a, b) for (ll i = ll(a); i >= ll(b); i--)
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
#define pb push_back
#define mp make_pair

#define pll pair<ll, ll>
using ll = long long;
using ld = long double;
const ll INF = 1LL << 60;
const ll mod = 1e9 + 7;
const ll mod2 = 998244353;
using namespace std;
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }

ll ceil_pow2(int n) {
  int x = 0;
  while ((1U << x) < (unsigned int)(n))
    x++;
  return x;
}

template <class S, S (*op)(S, S), S (*e)()> struct segtree {
public:
  segtree() : segtree(0) {}
  segtree(int n) : segtree(std::vector<S>(n, e())) {}
  segtree(const std::vector<S> &v) : _n(int(v.size())) {
    log = ceil_pow2(_n);
    size = 1 << log;
    d = std::vector<S>(2 * size, e());
    for (int i = 0; i < _n; i++)
      d[size + i] = v[i];
    for (int i = size - 1; i >= 1; i--) {
      update(i);
    }
  }

  void set(int p, S x) {
    assert(0 <= p && p < _n);
    p += size;
    d[p] = x;
    for (int i = 1; i <= log; i++)
      update(p >> i);
  }

  S get(int p) {
    assert(0 <= p && p < _n);
    return d[p + size];
  }

  S prod(int l, int r) {
    assert(0 <= l && l <= r && r <= _n);
    S sml = e(), smr = e();
    l += size;
    r += size;

    while (l < r) {
      if (l & 1)
        sml = op(sml, d[l++]);
      if (r & 1)
        smr = op(d[--r], smr);
      l >>= 1;
      r >>= 1;
    }
    return op(sml, smr);
  }

  S all_prod() { return d[1]; }

  template <bool (*f)(S)> int max_right(int l) {
    return max_right(l, [](S x) { return f(x); });
  }
  template <class F> int max_right(int l, F f) {
    assert(0 <= l && l <= _n);
    assert(f(e()));
    if (l == _n)
      return _n;
    l += size;
    S sm = e();
    do {
      while (l % 2 == 0)
        l >>= 1;
      if (!f(op(sm, d[l]))) {
        while (l < size) {
          l = (2 * l);
          if (f(op(sm, d[l]))) {
            sm = op(sm, d[l]);
            l++;
          }
        }
        return l - size;
      }
      sm = op(sm, d[l]);
      l++;
    } while ((l & -l) != l);
    return _n;
  }

  template <bool (*f)(S)> int min_left(int r) {
    return min_left(r, [](S x) { return f(x); });
  }
  template <class F> int min_left(int r, F f) {
    assert(0 <= r && r <= _n);
    assert(f(e()));
    if (r == 0)
      return 0;
    r += size;
    S sm = e();
    do {
      r--;
      while (r > 1 && (r % 2))
        r >>= 1;
      if (!f(op(d[r], sm))) {
        while (r < size) {
          r = (2 * r + 1);
          if (f(op(d[r], sm))) {
            sm = op(d[r], sm);
            r--;
          }
        }
        return r + 1 - size;
      }
      sm = op(d[r], sm);
    } while ((r & -r) != r);
    return 0;
  }

private:
  int _n, size, log;
  std::vector<S> d;

  void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
};

int op(int a, int b) { return max(a, b); }

int e() { return 0; }

int main() {
  ll n, k, a, ans = 0;
  cin >> n >> k;
  segtree<int, op, e> seg(300010);
  rep(i, 0, n) {
    cin >> a;

    ll l = max((ll)0, a - k);
    ll r = min(n, a + k);
    ll tmp = seg.prod(l, r + 1) + 1;
    ans = max(ans, tmp);
    seg.set(a, tmp);
  }
  cout << ans;
}

#include <bits/stdc++.h>
#define rep(i, a, b) for (ll i = ll(a); i < ll(b); i++)
#define irep(i, a, b) for (ll i = ll(a); i >= ll(b); i--)
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
#define pb push_back
#define mp make_pair

#define pll pair<ll, ll>
using ll = long long;
using ld = long double;
const ll INF = 1LL << 60;
const ll mod = 1e9 + 7;
const ll mod2 = 998244353;
using namespace std;
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }

ll ceil_pow2(int n) {
  int x = 0;
  while ((1U << x) < (unsigned int)(n))
    x++;
  return x;
}

template <class S, S (*op)(S, S), S (*e)()> struct segtree {
public:
  segtree() : segtree(0) {}
  segtree(int n) : segtree(std::vector<S>(n, e())) {}
  segtree(const std::vector<S> &v) : _n(int(v.size())) {
    log = ceil_pow2(_n);
    size = 1 << log;
    d = std::vector<S>(2 * size, e());
    for (int i = 0; i < _n; i++)
      d[size + i] = v[i];
    for (int i = size - 1; i >= 1; i--) {
      update(i);
    }
  }

  void set(int p, S x) {
    assert(0 <= p && p < _n);
    p += size;
    d[p] = x;
    for (int i = 1; i <= log; i++)
      update(p >> i);
  }

  S get(int p) {
    assert(0 <= p && p < _n);
    return d[p + size];
  }

  S prod(int l, int r) {
    assert(0 <= l && l <= r && r <= _n);
    S sml = e(), smr = e();
    l += size;
    r += size;

    while (l < r) {
      if (l & 1)
        sml = op(sml, d[l++]);
      if (r & 1)
        smr = op(d[--r], smr);
      l >>= 1;
      r >>= 1;
    }
    return op(sml, smr);
  }

  S all_prod() { return d[1]; }

  template <bool (*f)(S)> int max_right(int l) {
    return max_right(l, [](S x) { return f(x); });
  }
  template <class F> int max_right(int l, F f) {
    assert(0 <= l && l <= _n);
    assert(f(e()));
    if (l == _n)
      return _n;
    l += size;
    S sm = e();
    do {
      while (l % 2 == 0)
        l >>= 1;
      if (!f(op(sm, d[l]))) {
        while (l < size) {
          l = (2 * l);
          if (f(op(sm, d[l]))) {
            sm = op(sm, d[l]);
            l++;
          }
        }
        return l - size;
      }
      sm = op(sm, d[l]);
      l++;
    } while ((l & -l) != l);
    return _n;
  }

  template <bool (*f)(S)> int min_left(int r) {
    return min_left(r, [](S x) { return f(x); });
  }
  template <class F> int min_left(int r, F f) {
    assert(0 <= r && r <= _n);
    assert(f(e()));
    if (r == 0)
      return 0;
    r += size;
    S sm = e();
    do {
      r--;
      while (r > 1 && (r % 2))
        r >>= 1;
      if (!f(op(d[r], sm))) {
        while (r < size) {
          r = (2 * r + 1);
          if (f(op(d[r], sm))) {
            sm = op(d[r], sm);
            r--;
          }
        }
        return r + 1 - size;
      }
      sm = op(d[r], sm);
    } while ((r & -r) != r);
    return 0;
  }

private:
  int _n, size, log;
  std::vector<S> d;

  void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
};

int op(int a, int b) { return max(a, b); }

int e() { return 0; }

int main() {
  ll n, k, a, ans = 0;
  cin >> n >> k;
  segtree<int, op, e> seg(300010);
  rep(i, 0, n) {
    cin >> a;

    ll l = max((ll)0, a - k);
    ll r = min(300000LL, a + k);
    ll tmp = seg.prod(l, r + 1) + 1;
    ans = max(ans, tmp);
    seg.set(a, tmp);
  }
  cout << ans;
}


#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define all(x) (x).begin(), (x).end()

typedef vector<int> vi;

const int N = 300010;
int nxt = 0;
int root[N];

struct Node {
  int ls, rs, val, id = 0;
} node[N * 50];

void update(int &n, int pre, int b, int e, int pos, int id) {
  n = ++nxt;
  node[n] = node[pre];
  if (b == e && b == pos) {
    node[n].val++;
    node[n].id = max(node[n].id, id);
    node[n].ls = node[n].rs = 0;
    return;
  }
  int mid = (b + e) / 2;
  if (pos <= mid)
    update(node[n].ls, node[pre].ls, b, mid, pos, id);
  else
    update(node[n].rs, node[pre].rs, mid + 1, e, pos, id);
  node[n].val = node[node[n].ls].val + node[node[n].rs].val;
  node[n].id = max(node[node[n].ls].id, node[node[n].rs].id);
}
int q;
vi A;

int query_sum(int root, int b, int e, int l, int r) {

  if (l > r)
    return 0;
  if (l > e || b > r)
    return 0;
  if (b == l && r == e) {
    return node[root].val;
  }
  int mid = (b + e) / 2;
  return query_sum(node[root].ls, b, mid, l, min(r, mid)) +
         query_sum(node[root].rs, mid + 1, e, max(l, mid + 1), r);
}

int query(int root, int b, int e, int l, int r) {
  if (l > r)
    return 0;
  if (l > e || b > r)
    return 0;
  if (b == l && r == e)
    return node[root].id;
  int mid = (b + e) / 2;
  return max(query(node[root].ls, b, mid, l, min(r, mid)),
             query(node[root].rs, mid + 1, e, max(l, mid + 1), r));
}

int main() {
  int n;
  cin >> n >> q;
  int K = 300000;
  A.resize(K);
  for (int j = 0; j < n; ++j) {
    cin >> A[j];
  }
  vi ans(K, 1);
  int res = 1;
  for (int k = 1; k <= n; ++k)
    update(root[k], root[k - 1], 0, K - 1, A[k - 1],
           k - 1); // 0 -> is the initial empty segment tree

  for (int i = 1; i <= n; ++i) {
    int sum1 = query_sum(root[i - 1], 0, K - 1, max(A[i - 1] - q, 0), A[i - 1]);
    int sum2 =
        query_sum(root[i - 1], 0, K - 1, A[i - 1], min(K - 1, A[i - 1] + q));
    if (sum1) {
      int ind = query(root[i - 1], 0, K - 1, max(A[i - 1] - q, 0), A[i - 1]);
      ans[i - 1] = 1 + ans[ind];
    }
    if (sum2) {
      int ind =
          query(root[i - 1], 0, K - 1, A[i - 1], min(K - 1, A[i - 1] + q));
      ans[i - 1] = max(ans[i - 1], 1 + ans[ind]);
    }

    res = max(res, ans[i - 1]);
  }
  cout << res << "\\n";
  cout << nxt << "\\n";
}

#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define all(x) (x).begin(), (x).end()

typedef vector<int> vi;

const int N = 300010;
int nxt = 0;
int root[N];

struct Node {
  int ls, rs, val, id = 0;
} node[N * 50];

void update(int &n, int pre, int b, int e, int pos, int id) {
  n = ++nxt;
  node[n] = node[pre];
  if (b == e && b == pos) {
    node[n].val++;
    node[n].id = max(node[n].id, id);
    node[n].ls = node[n].rs = 0;
    return;
  }
  int mid = (b + e) / 2;
  if (pos <= mid)
    update(node[n].ls, node[pre].ls, b, mid, pos, id);
  else
    update(node[n].rs, node[pre].rs, mid + 1, e, pos, id);
  node[n].val = node[node[n].ls].val + node[node[n].rs].val;
  node[n].id = max(node[node[n].ls].id, node[node[n].rs].id);
}
int q;
vi A;

int query_sum(int root, int b, int e, int l, int r) {

  if (l > r)
    return 0;
  if (l > e || b > r)
    return 0;
  if (b == l && r == e) {
    return node[root].val;
  }
  int mid = (b + e) / 2;
  return query_sum(node[root].ls, b, mid, l, min(r, mid)) +
         query_sum(node[root].rs, mid + 1, e, max(l, mid + 1), r);
}

int query(int root, int b, int e, int l, int r) {
  if (l > r)
    return 0;
  if (l > e || b > r)
    return 0;
  if (b == l && r == e)
    return node[root].id;
  int mid = (b + e) / 2;
  return max(query(node[root].ls, b, mid, l, min(r, mid)),
             query(node[root].rs, mid + 1, e, max(l, mid + 1), r));
}

int main() {
  int n;
  cin >> n >> q;
  int K = 300001;
  A.resize(K);
  for (int j = 0; j < n; ++j) {
    cin >> A[j];
  }
  vi ans(K, 1);
  int res = 1;
  for (int k = 1; k <= n; ++k)
    update(root[k], root[k - 1], 0, K - 1, A[k - 1],
           k - 1); // 0 -> is the initial empty segment tree

  for (int i = 1; i <= n; ++i) {
    int sum1 = query_sum(root[i - 1], 0, K - 1, max(A[i - 1] - q, 0), A[i - 1]);
    int sum2 =
        query_sum(root[i - 1], 0, K - 1, A[i - 1], min(K - 1, A[i - 1] + q));
    if (sum1) {
      int ind = query(root[i - 1], 0, K - 1, max(A[i - 1] - q, 0), A[i - 1]);
      ans[i - 1] = 1 + ans[ind];
    }
    if (sum2) {
      int ind =
          query(root[i - 1], 0, K - 1, A[i - 1], min(K - 1, A[i - 1] + q));
      ans[i - 1] = max(ans[i - 1], 1 + ans[ind]);
    }

    res = max(res, ans[i - 1]);
  }
  cout << res << "\\n";
}


#include <bits/stdc++.h>
#define REP(i, s, n) for (int i = s; i < (int)(n); i++)
#define ALL(a) a.begin(), a.end()
#define MOD 1000000007
using namespace std;
using ll = long long;

int N, K;
vector<int> memo;
vector<int> A;

int search(int pos) {
  if (memo[pos] != -1)
    return memo[pos];

  int max_cnt = 0;
  REP(i, pos + 1, N) {
    if (abs(A[i] - A[pos]) <= K)
      max_cnt = max(max_cnt, search(i));
  }

  return memo[pos] = (max_cnt + 1);
}

int main() {
  cin.tie(0);
  cout.tie(0);
  ios::sync_with_stdio(false);
  cin >> N >> K;
  A.resize(N);
  REP(i, 0, N) cin >> A[i];

  memo.resize(N, -1);
  int ans = 0;
  REP(i, 0, N) { ans = max(ans, search(i)); }
  cout << ans << endl;
  return 0;
}

#include <bits/stdc++.h>
#define REP(i, s, n) for (int i = s; i < (int)(n); i++)
#define ALL(a) a.begin(), a.end()
#define MOD 1000000007
using namespace std;
using ll = long long;

template <typename T> class LazySegmentTree {
  using fn = function<T(T, T)>;

public:
  LazySegmentTree(vector<T> &base, fn _fx, fn _fa, fn _fm, T _ex, T _em)
      : fx(_fx), fa(_fa), fm(_fm), ex(_ex), em(_em) {
    n = 1;
    while (n < base.size())
      n *= 2;

    node.resize(2 * n - 1, ex);
    REP(i, 0, base.size()) node[n - 1 + i] = base[i];
    for (int i = n - 2; i >= 0; i--)
      node[i] = fx(node[2 * i + 1], node[2 * i + 2]);

    lazy.resize(2 * n - 1, em);
  }

  void eval(int k, int l, int r) {
    if (lazy[k] == em)
      return;

    if (r - l > 1) {
      lazy[2 * k + 1] = fm(lazy[2 * k + 1], lazy[k]);
      lazy[2 * k + 2] = fm(lazy[2 * k + 2], lazy[k]);
    }
    node[k] = fa(node[k], lazy[k]);
    lazy[k] = em;
  }

  void update(int a, int b, T x, int k = 0, int l = 0, int r = -1) {
    if (r < 0)
      r = n;
    eval(k, l, r);
    if (r <= a || b <= l)
      return;
    if (a <= l && r <= b) {
      lazy[k] = fm(lazy[k], x);
      eval(k, l, r);
    } else {
      update(a, b, x, 2 * k + 1, l, (l + r) / 2);
      update(a, b, x, 2 * k + 2, (l + r) / 2, r);
      node[k] = fx(node[2 * k + 1], node[2 * k + 2]);
    }
  }

  T query(int a, int b, int k = 0, int l = 0, int r = -1) {
    if (r < 0)
      r = n;
    eval(k, l, r);
    if (r <= a || b <= l)
      return ex;
    if (a <= l && r <= b)
      return node[k];
    T vl = query(a, b, 2 * k + 1, l, (l + r) / 2);
    T vr = query(a, b, 2 * k + 2, (l + r) / 2, r);
    return fx(vl, vr);
  }

  void print(int w = 4) {
    cout << "#node : " << endl;
    int prev = 0;
    for (int i = 1; i <= n; i *= 2) {
      for (int j = prev; j < prev + i; j++) {
        cout << setw(n * w / i) << setfill(' ');
        if (node[j] == ex)
          cout << "ex";
        else
          cout << node[j];
      }
      cout << endl;
      prev += i;
    }
    cout << "#lazy : " << endl;
    prev = 0;
    for (int i = 1; i <= n; i *= 2) {
      for (int j = prev; j < prev + i; j++) {
        cout << setw(n * w / i) << setfill(' ');
        if (lazy[j] == em)
          cout << "em";
        else
          cout << lazy[j];
      }
      cout << endl;
      prev += i;
    }
  }

private:
  int n;
  vector<T> node, lazy;
  fn fx, fa, fm;
  T ex, em;
};

int main() {
  int N, K;
  cin >> N >> K;
  vector<int> A(N);
  int maxv = 0;
  REP(i, 0, N) {
    cin >> A[i];
    maxv = max(maxv, A[i]);
  }

  auto fx = [](auto l, auto r) { return max(l, r); };
  auto fa = [](auto l, auto r) { return max(l, r); };
  auto fm = [](auto l, auto r) { return max(l, r); };
  vector<int> base(maxv + 1, 0);
  REP(i, 0, N) base[A[i]] = 1;
  LazySegmentTree<int> seg(base, fx, fa, fm, 0, 0);

  int ans = 1;
  for (int i = N - 1; i >= 0; i--) {
    int cur = seg.query(A[i], A[i] + 1);
    ans = max(ans, cur);
    seg.update(max(0, A[i] - K), min(maxv + 1, A[i] + K + 1), cur + 1);
  }
  cout << ans << endl;

  return 0;
}


#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using P = pair<int, int>;
#define rep(i, n) for (int i = 0; i < (n); ++i)

int main() {
  int n, k;
  cin >> n >> k;
  vector<int> a(n);
  rep(i, n) cin >> a[i];
  vector<int> dis(n), pre(n);
  for (int i = 0; i < n; i++) {
    dis[i] = 1;
    pre[i] = -1;
    for (int j = i - 1; j >= 0; j--) {
      if (abs(a[i] - a[j]) <= k && dis[j] + 1 > dis[i]) {
        pre[i] = j;
        dis[i] = dis[j] + 1;
      }
    }
  }
  cout << dis[n - 1] << endl;
  return 0;
}

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using P = pair<int, int>;
#define rep(i, n) for (int i = 0; i < (n); ++i)

const int N = 6e5 + 7;
int n, a[N], k, tree[4 * N];

#define m (l + r) / 2
#define lson 2 * node
#define rson 2 * node + 1

void update(int pos, int v, int l, int r, int node) {
  if (l == r) {
    tree[node] = v;
    return;
  }
  if (pos <= m)
    update(pos, v, l, m, lson);
  else
    update(pos, v, m + 1, r, rson);
  tree[node] = max(tree[lson], tree[rson]);
}

int query(int ql, int qr, int l, int r, int node) {
  if (ql <= l && qr >= r)
    return tree[node];
  int ans = 0;
  if (ql <= m)
    ans = max(ans, query(ql, qr, l, m, lson));
  if (qr > m)
    ans = max(ans, query(ql, qr, m + 1, r, rson));
  return ans;
}

int main() {
  cin >> n >> k;
  rep(i, n) cin >> a[i + 1];
  int ans = 0;
  for (int i = 1; i <= n; ++i) {
    int res = query(max(a[i] - k, 0), a[i] + k, 0, N, 1) + 1;
    ans = max(ans, res);
    update(a[i], res, 0, N, 1);
  }
  cout << ans << endl;
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5 + 50;
int maxx[maxn << 2], a[maxn], f[maxn];
void change(int rt, int l, int r, int pos, int v) {
  if (l == r && l == pos) {
    maxx[l] = v;
    return;
  }
  int mid = (l + r) >> 1;
  if (pos > mid)
    change(rt << 1 | 1, mid + 1, r, pos, v);
  else
    change(rt << 1, l, mid, pos, v);
  maxx[rt] = max(maxx[rt << 1], maxx[rt << 1 | 1]);
}
int query(int rt, int l, int r, int x, int y) {
  if (x >= l && r <= y) {
    return maxx[rt];
  }
  int ans = 0;
  int mid = (l + r) >> 1;
  if (mid >= x)
    ans = max(ans, query(rt << 1, l, mid, x, y));
  if (mid < y)
    ans = max(ans, query(rt << 1 | 1, mid + 1, r, x, y));
  return ans;
}
int n, k;
int main() {
  cin >> n >> k;
  for (int i = 1; i <= n; ++i)
    cin >> a[i];
  f[1] = 1;
  change(1, 0, 3e5, a[1], 1);
  for (int i = 2; i <= n; ++i) {
    int now = query(1, 0, 3e5, max(a[i] - k, 0), min(300000, a[i] + k));
    f[i] = max(1, now + 1);
    now = query(1, 0, 3e5, a[i], a[i]);
    if (now < f[i])
      change(1, 0, 3e5, a[i], f[i]);
  }
  int Max = 0;
  for (int i = 1; i <= n; ++i)
    Max = max(f[i], Max);
  cout << Max << endl;
  return 0;
}

#include <bits/stdc++.h>
using namespace std;
const int N = 3e5 + 50;
int maxn[N << 2], a[N], f[N];
/*void change(int rt,int l,int r,int pos,int v)
{
        if(l==r&&l==pos)
        {
                maxx[rt]=v;
                return ;
        }
        int mid=(l+r)>>1;
        if(pos>mid) change(rt<<1|1,mid+1,r,pos,v);
        else change(rt<<1,l,mid,pos,v);
        maxx[rt]=max(maxx[rt<<1],maxx[rt<<1|1]);
}
int query(int rt,int l,int r,int x,int y)
{
        if(x>=l&&r<=y)
        {
                return maxx[rt];
        }
        int ans=0;
        int mid=(l+r)>>1;
        if(x<=mid) ans=max(ans,query(rt<<1,l,mid,x,y));
        if(mid<y) ans=max(ans,query(rt<<1|1,mid+1,r,x,y));
        return ans;
}*/
void change(int k, int l, int r, int pos, int v) {
  if (l == pos && pos == r) {
    maxn[k] = v;
    return;
  }
  int mid = l + r >> 1;
  if (pos <= mid)
    change(k << 1, l, mid, pos, v);
  else
    change(k << 1 | 1, mid + 1, r, pos, v);
  maxn[k] = max(maxn[k << 1], maxn[k << 1 | 1]);
}

int query(int k, int l, int r, int qx, int qy) {
  if (qx <= l && r <= qy)
    return maxn[k];
  int mid = l + r >> 1;
  int ans = 0;
  if (qx <= mid)
    ans = max(ans, query(k << 1, l, mid, qx, qy));
  if (mid < qy)
    ans = max(ans, query(k << 1 | 1, mid + 1, r, qx, qy));
  return ans;
}
int n, k;
int main() {
  cin >> n >> k;
  for (int i = 1; i <= n; ++i)
    cin >> a[i];
  f[1] = 1;
  change(1, 0, 3e5, a[1], 1);
  for (int i = 2; i <= n; ++i) {
    int now = query(1, 0, 3e5, max(a[i] - k, 0), min(300000, a[i] + k));
    f[i] = max(1, now + 1);
    now = query(1, 0, 3e5, a[i], a[i]);
    if (now < f[i])
      change(1, 0, 3e5, a[i], f[i]);
  }
  int Max = 0;
  for (int i = 1; i <= n; ++i)
    Max = max(f[i], Max);
  cout << Max << endl;
  return 0;
}


// #pragma GCC optimize("Ofast")
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,fma")
// #pragma GCC optimize("unroll-loops")

#include "bits/stdc++.h"

using namespace std;

#define PI 3.1415926535897932384626433832795l

#define pb push_back
#define mp make_pair
#define lb lower_bound // First element which is not less than val
#define ub upper_bound // First element greater than val
#define f first
#define s second

using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vb = vector<bool>;
using vd = vector<double>;
using vs = vector<string>;
using vpii = vector<pair<int, int>>;
using vpll = vector<pair<ll, ll>>;

using pii = pair<int, int>;
using pll = pair<ll, ll>;

#define endl '\\n'
#define re return
#define repz(i, a) for (ll i = 0; i < (a); i++)
#define vecin(n, v)                                                            \\
  for (ll i = 0; i < n; i++)                                                   \\
    cin >> v[i];
#define full(v) v.begin(), v.end()

struct S {
  int x;

  // This should be the identity element
  S() { x = 0; }

  S(int _x) : x(_x) {}
};

S op(S &a, S &b) { return {max(a.x, b.x)}; }

// Predicate for binary search. Must be true for identity.
bool f(S /*x*/) {
  // Dummy for binary search
  return true;
}

struct segtree {
  int _n;
  vector<S> t;
  int size;
  int log;

  segtree() : segtree(0) {}

  segtree(int n = -1) {
    if (n >= 0)
      init(n);
  }

  void init(int n) {
    _n = n;
    log = 0;
    while ((1U << log) < (unsigned int)(n))
      log++;
    size = 1 << log;
    t.assign(2 * _n, S());
  }

  void build(vector<S> v) {
    init((int)v.size());
    assert(_n != 0);

    for (int i = 0; i < _n; i++)
      t[size + i] = v[i];

    for (int i = size - 1; i > 0; i--)
      t[i] = op(t[2 * i], t[2 * i + 1]);
  }

  void set(int p, S x) {
    assert(0 <= p && p < _n);
    p += size;
    t[p] = x;
    for (int i = 1; i <= log; i++)
      t[p >> i] = op(t[2 * (p >> i)], t[2 * (p >> i) + 1]);
  }

  S get(int p) {
    assert(0 <= p && p < _n);
    return t[p + size];
  }

  // Find result for range [l,r)
  S query(int l, int r) {
    assert(0 <= l && l <= r && r <= _n);
    S ansl, ansr;
    l += size;
    r += size;
    while (l < r) {
      if (l & 1)
        ansl = op(ansl, t[l++]);
      if (r & 1)
        ansr = op(t[--r], ansr);
      l >>= 1;
      r >>= 1;
    }
    return op(ansl, ansr);
  }

  /* Binary Search */
  // Find the maximum value of r such that [l,r) is true
  int max_right(int l) {
    assert(0 <= l && l <= _n);

    if (l == _n)
      return _n;
    l += size;
    S sm;
    do {
      while (l % 2 == 0)
        l >>= 1;
      if (!f(op(sm, t[l]))) {
        while (l < size) {
          l *= 2;
          if (f(op(sm, t[l]))) {
            sm = op(sm, t[l]);
            l++;
          }
        }
        return l - size;
      }
      sm = op(sm, t[l]);
      l++;
    } while ((l & -l) != l);
    return _n;
  }

  // This is the minimum l such that [l,r) is true
  int min_left(int r) {
    assert(0 <= r && r <= _n);
    if (r == 0)
      return 0;
    r += size;
    S sm;
    do {
      r--;
      while (r > 1 && (r % 2))
        r >>= 1;
      if (!f(op(t[r], sm))) {
        while (r < size) {
          r = (2 * r + 1);
          if (f(op(t[r], sm))) {
            sm = op(t[r], sm);
            r--;
          }
        }
        return r + 1 - size;
      }
      sm = op(t[r], sm);
    } while ((r & -r) != r);
    return 0;
  }
};

const int N = 6e5 + 57;

void solve() {
  int n, k;
  cin >> n >> k;
  vi a(n);
  vecin(n, a);
  segtree T(N);
  repz(i, n) {
    S s = T.query(max(a[i] - k, 0), a[i] + k + 1);
    T.set(a[i], {s.x + 1});
  }
  cout << T.t[1].x << endl;
  ;
}

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);

  ll t = 1;
  // cin >> t;
  while (t--) {
    solve();
  }
}

// #pragma GCC optimize("Ofast")
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,fma")
// #pragma GCC optimize("unroll-loops")

#include "bits/stdc++.h"

using namespace std;

#define PI 3.1415926535897932384626433832795l

#define pb push_back
#define mp make_pair
#define lb lower_bound // First element which is not less than val
#define ub upper_bound // First element greater than val
#define f first
#define s second

using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vb = vector<bool>;
using vd = vector<double>;
using vs = vector<string>;
using vpii = vector<pair<int, int>>;
using vpll = vector<pair<ll, ll>>;

using pii = pair<int, int>;
using pll = pair<ll, ll>;

#define endl '\\n'
#define re return
#define repz(i, a) for (ll i = 0; i < (a); i++)
#define vecin(n, v)                                                            \\
  for (ll i = 0; i < n; i++)                                                   \\
    cin >> v[i];
#define full(v) v.begin(), v.end()

struct S {
  int x;

  // This should be the identity element
  S() { x = 0; }

  S(int _x) : x(_x) {}
};

S op(S &a, S &b) { return {max(a.x, b.x)}; }

// Predicate for binary search. Must be true for identity.
bool f(S /*x*/) {
  // Dummy for binary search
  return true;
}

struct segtree {
  int _n;
  vector<S> t;
  int size;
  int log;

  segtree() : segtree(0) {}

  segtree(int n = -1) {
    if (n >= 0)
      init(n);
  }

  void init(int n) {
    _n = n;
    log = 0;
    while ((1U << log) < (unsigned int)(n))
      log++;
    size = 1 << log;
    t.assign(2 * size, S());
  }

  void build(vector<S> v) {
    init((int)v.size());
    assert(_n != 0);

    for (int i = 0; i < _n; i++)
      t[size + i] = v[i];

    for (int i = size - 1; i > 0; i--)
      t[i] = op(t[2 * i], t[2 * i + 1]);
  }

  void set(int p, S x) {
    assert(0 <= p && p < _n);
    p += size;
    t[p] = x;
    for (int i = 1; i <= log; i++)
      t[p >> i] = op(t[2 * (p >> i)], t[2 * (p >> i) + 1]);
  }

  S get(int p) {
    assert(0 <= p && p < _n);
    return t[p + size];
  }

  // Find result for range [l,r)
  S query(int l, int r) {
    assert(0 <= l && l <= r && r <= _n);
    S ansl, ansr;
    l += size;
    r += size;
    while (l < r) {
      if (l & 1)
        ansl = op(ansl, t[l++]);
      if (r & 1)
        ansr = op(t[--r], ansr);
      l >>= 1;
      r >>= 1;
    }
    return op(ansl, ansr);
  }

  /* Binary Search */
  // Find the maximum value of r such that [l,r) is true
  int max_right(int l) {
    assert(0 <= l && l <= _n);

    if (l == _n)
      return _n;
    l += size;
    S sm;
    do {
      while (l % 2 == 0)
        l >>= 1;
      if (!f(op(sm, t[l]))) {
        while (l < size) {
          l *= 2;
          if (f(op(sm, t[l]))) {
            sm = op(sm, t[l]);
            l++;
          }
        }
        return l - size;
      }
      sm = op(sm, t[l]);
      l++;
    } while ((l & -l) != l);
    return _n;
  }

  // This is the minimum l such that [l,r) is true
  int min_left(int r) {
    assert(0 <= r && r <= _n);
    if (r == 0)
      return 0;
    r += size;
    S sm;
    do {
      r--;
      while (r > 1 && (r % 2))
        r >>= 1;
      if (!f(op(t[r], sm))) {
        while (r < size) {
          r = (2 * r + 1);
          if (f(op(t[r], sm))) {
            sm = op(t[r], sm);
            r--;
          }
        }
        return r + 1 - size;
      }
      sm = op(t[r], sm);
    } while ((r & -r) != r);
    return 0;
  }
};

const int N = 6e5 + 57;

void solve() {
  int n, k;
  cin >> n >> k;
  vi a(n);
  vecin(n, a);
  segtree T(N);
  repz(i, n) {
    S s = T.query(max(a[i] - k, 0), a[i] + k + 1);
    T.set(a[i], {s.x + 1});
  }
  cout << T.t[1].x << endl;
  ;
}

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);

  ll t = 1;
  // cin >> t;
  while (t--) {
    solve();
  }
}


// #pragma GCC optimize("Ofast")
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,fma")
// #pragma GCC optimize("unroll-loops")

#include "bits/stdc++.h"

using namespace std;

#define PI 3.1415926535897932384626433832795l

#define pb push_back
#define mp make_pair
#define lb lower_bound // First element which is not less than val
#define ub upper_bound // First element greater than val
#define f first
#define s second

using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vb = vector<bool>;
using vd = vector<double>;
using vs = vector<string>;
using vpii = vector<pair<int, int>>;
using vpll = vector<pair<ll, ll>>;

using pii = pair<int, int>;
using pll = pair<ll, ll>;

#define endl '\\n'
#define re return
#define repz(i, a) for (ll i = 0; i < (a); i++)
#define vecin(n, v)                                                            \\
  for (ll i = 0; i < n; i++)                                                   \\
    cin >> v[i];
#define full(v) v.begin(), v.end()

// struct node {
// int x;

// node()
//{
// x = 0;
//}

// node(int _x):x(_x){}

// void combine(node& other)
//{
// x = min(x,other.x);
//}

// void combine(node& a, node& b)
//{
//*this = a;
// combine(b);
//}
//};

// int right_half[32];
// struct segtree
//{
// int tree_n = 0;
// vector<node> t;

// segtree(int n = -1)
//{
// if (n >= 0)
// init(n);
//}

// void init(int n)
//{
// tree_n = n;
// t.assign(2*tree_n,node());
//}

// void build(vector<node> v)
//{
// int n = (int)v.size();
// init(n);
// assert(n <= tree_n);

// for (int i = 0; i < n; i++)
// t[tree_n+i] = v[i];

// for (int i = n-1; i > 0; i--)
// t[i].combine(t[2*i],t[2*i+1]);
//}

// node query(int a, int b)
//{
// assert(0 <= a && a <= b && b <= tree_n);
// node ans;

// int r_size = 0;
// for (a += tree_n, b += tree_n; a < b; a /= 2, b /= 2)
//{
// if (a&1)
// ans.combine(t[a++]);
// if (b&1)
// right_half[r_size++] = --b;
//}
// for (int i = r_size-1; i >= 0; i--)
// ans.combine(t[right_half[i]]);

// return ans;
//}

// node query_single(int a)
//{
// assert(a >= 0 && a < tree_n);
// return t[tree_n+a];
//}

// void join_up(int pos)
//{
// while (pos > 1)
//{
// pos /= 2;
// t[pos].combine(t[2*pos],t[2*pos+1]);
//}
//}

// void update(int index, node& a)
//{
// assert(index >= 0 && index < tree_n);
// int pos = tree_n+index;
// t[pos] = a;
// join_up(pos);
//}
//};

const int N = 3e5 + 30; // limit for array size
int n;                  // array size
int t[2 * N];

void build() { // build the tree
  for (int i = n - 1; i > 0; --i)
    t[i] = max(t[i << 1], t[i << 1 | 1]);
}

void modify(int p, int value) { // set value at position p
  for (t[p + n] = max(value, t[p + n]), p += n; p > 1; p >>= 1)
    t[p >> 1] = max(t[p], t[p ^ 1]);
}

int query(int l, int r) { // sum on interval [l, r)
  int res = 0;
  for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
    if (l & 1)
      res = max(res, t[l++]);
    if (r & 1)
      res = max(t[--r], res);
  }
  return res;
}

void solve() {
  int k;
  cin >> n >> k;
  vi a(n);
  vecin(n, a);

  for (int i = 0; i < n; i++) {
    int x = query(max(a[i] - k, 0), a[i] + k + 1);
    // cout << x << " " << a[i] << endl;;
    modify(a[i], x + 1);
  }

  cout << query(0, 3e5 + 7) << endl;
}

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);

  ll t = 1;
  // cin >> t;
  while (t--) {
    solve();
  }
}

// #pragma GCC optimize("Ofast")
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,fma")
// #pragma GCC optimize("unroll-loops")

#include "bits/stdc++.h"

using namespace std;

#define PI 3.1415926535897932384626433832795l

#define pb push_back
#define mp make_pair
#define lb lower_bound // First element which is not less than val
#define ub upper_bound // First element greater than val
#define f first
#define s second

using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vb = vector<bool>;
using vd = vector<double>;
using vs = vector<string>;
using vpii = vector<pair<int, int>>;
using vpll = vector<pair<ll, ll>>;

using pii = pair<int, int>;
using pll = pair<ll, ll>;

#define endl '\\n'
#define re return
#define repz(i, a) for (ll i = 0; i < (a); i++)
#define vecin(n, v)                                                            \\
  for (ll i = 0; i < n; i++)                                                   \\
    cin >> v[i];
#define full(v) v.begin(), v.end()

struct node {
  int x;

  node() { x = 0; }

  node(int _x) : x(_x) {}

  void combine(node &other) { x = max(x, other.x); }

  void combine(node &a, node &b) {
    *this = a;
    combine(b);
  }
};

int right_half[32];
struct segtree {
  int tree_n = 0;
  vector<node> t;

  segtree(int n = -1) {
    if (n >= 0)
      init(n);
  }

  void init(int n) {
    tree_n = n;
    t.assign(2 * tree_n, node());
  }

  void build(vector<node> v) {
    int n = (int)v.size();
    init(n);
    assert(n <= tree_n);

    for (int i = 0; i < n; i++)
      t[tree_n + i] = v[i];

    for (int i = n - 1; i > 0; i--)
      t[i].combine(t[2 * i], t[2 * i + 1]);
  }

  node query(int a, int b) {
    assert(0 <= a && a <= b && b <= tree_n);
    node ans;

    int r_size = 0;
    for (a += tree_n, b += tree_n; a < b; a /= 2, b /= 2) {
      if (a & 1)
        ans.combine(t[a++]);
      if (b & 1)
        right_half[r_size++] = --b;
    }
    for (int i = r_size - 1; i >= 0; i--)
      ans.combine(t[right_half[i]]);

    return ans;
  }

  node query_single(int a) {
    assert(a >= 0 && a < tree_n);
    return t[tree_n + a];
  }

  void join_up(int pos) {
    while (pos > 1) {
      pos /= 2;
      t[pos].combine(t[2 * pos], t[2 * pos + 1]);
    }
  }

  void update(int index, node &a) {
    assert(index >= 0 && index < tree_n);
    int pos = tree_n + index;
    t[pos] = a;
    join_up(pos);
  }
};

void solve() {
  int n, k;
  cin >> n >> k;
  vi a(n);
  vecin(n, a);
  segtree T(6e5 + 7);

  for (int i = 0; i < n; i++) {
    int x = T.query(max(a[i] - k, 0), a[i] + k + 1).x;
    node t(x + 1);
    T.update(a[i], t);
  }

  cout << T.query(0, 3e5 + 6).x << endl;
}

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);

  ll t = 1;
  // cin >> t;
  while (t--) {
    solve();
  }
}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
#define all(v) v.begin(), v.end()
#define rep(i, n) for (ll i = 0; i < (ll)(n); i++)
#define Rep(n) for (ll _ = 0; _ < (ll)(n); _++)

template <class S> S sum(vector<S> &a) { return accumulate(all(a), S()); }
template <class S> S max(vector<S> &a) { return *max_element(all(a)); }
template <class S> S min(vector<S> &a) { return *min_element(all(a)); }
ll max(int a, ll b) { return max((ll)a, b); }
ll max(ll a, int b) { return max(a, (ll)b); }
ll min(int a, ll b) { return min((ll)a, b); }
ll min(ll a, int b) { return min(a, (ll)b); }

void eprint() { cerr << endl; }
template <class First, class... Rest> void eprint(First &f, Rest &...r) {
  cerr << f << ' ';
  eprint(r...);
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
  size_t output_num = v.size();
  bool is_omitted = false;
#ifdef OUTPUT_VECTOR_MAX
  if (OUTPUT_VECTOR_MAX < output_num) {
    output_num = OUTPUT_VECTOR_MAX;
    is_omitted = true;
  }
#endif
  os << "[";
  for (size_t i = 0; i < output_num - 1; i++)
    os << v[i] << ", ";
  os << v[output_num - 1];
  if (is_omitted)
    os << ", ...";
  return os << "]";
}

void Main();
int main() {
  cin.tie(nullptr);
  ios_base::sync_with_stdio(false);
  cout << fixed << setprecision(20);
  Main();
  return 0;
}

void Main() {
  int n, k;
  cin >> n >> k;
  vector<int> a(n);
  rep(i, n) cin >> a[i];
  vector<int> dp(n, 1);
  for (int i = n - 1; i >= 0; i--) {
    for (int j = i + 1; j < n; j++) {
      if (abs(a[i] - a[j]) <= k) {
        dp[i] = max(dp[i], dp[j] + 1);
      }
    }
  }
  cout << max(dp) << endl;
}

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
#define all(v) v.begin(), v.end()
#define rep(i, n) for (ll i = 0; i < (ll)(n); i++)
#define Rep(n) for (ll _ = 0; _ < (ll)(n); _++)

template <class S> S sum(vector<S> &a) { return accumulate(all(a), S()); }
template <class S> S max(vector<S> &a) { return *max_element(all(a)); }
template <class S> S min(vector<S> &a) { return *min_element(all(a)); }
ll max(int a, ll b) { return max((ll)a, b); }
ll max(ll a, int b) { return max(a, (ll)b); }
ll min(int a, ll b) { return min((ll)a, b); }
ll min(ll a, int b) { return min(a, (ll)b); }

void eprint() { cerr << endl; }
template <class First, class... Rest> void eprint(First &f, Rest &...r) {
  cerr << f << ' ';
  eprint(r...);
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
  size_t output_num = v.size();
  bool is_omitted = false;
#ifdef OUTPUT_VECTOR_MAX
  if (OUTPUT_VECTOR_MAX < output_num) {
    output_num = OUTPUT_VECTOR_MAX;
    is_omitted = true;
  }
#endif
  os << "[";
  for (size_t i = 0; i < output_num - 1; i++)
    os << v[i] << ", ";
  os << v[output_num - 1];
  if (is_omitted)
    os << ", ...";
  return os << "]";
}

void Main();
int main() {
  cin.tie(nullptr);
  ios_base::sync_with_stdio(false);
  cout << fixed << setprecision(20);
  Main();
  return 0;
}

#include <atcoder/segtree>
using namespace atcoder;

int zero() { return 0; }
int op(int a, int b) { return max(a, b); }

void Main() {
  int n, k;
  cin >> n >> k;
  vector<int> a(n);
  rep(i, n) cin >> a[i];
  segtree<int, op, zero> dp(300001);
  rep(i, n) {
    int l = max(0, a[i] - k);
    int r = min(300001, a[i] + k + 1);
    dp.set(a[i], dp.prod(l, r) + 1);
  }
  cout << dp.all_prod() << endl;
}


#include "stdio.h"

#define MAX(a, b) (((a) > (b)) ? (a) : (b))

struct segtree {
  int l;
  int r;
  int max;
} tree[300010 * 4];

int dp[300010];
int seq[300010];

int modify(int i, int dis, int val) {
  if (tree[i].l == tree[i].r) {
    tree[i].max = val;
    return 0;
  }
  int mid = (tree[i].l + tree[i].r) >> 1;
  if (dis > mid)
    modify(2 * i + 1, dis, val);
  else
    modify(2 * i, dis, val);
  if (tree[i].max < val)
    tree[i].max = val;
  return 0;
}

int search(int i, int l, int r) {
  if (tree[i].l >= l && tree[i].r <= r)
    return tree[i].max;
  else if (tree[i].l > r || tree[i].r < l)
    return 0;
  else
    return MAX(search(2 * i, l, r), search(2 * i + 1, l, r));
}

int build(int i, int l, int r) {
  tree[i].l = l;
  tree[i].r = r;
  tree[i].max = 0;
  if (l == r)
    return 0;
  int mid = (l + r) >> 1;
  build(2 * i, l, mid);
  build(2 * i + 1, mid + 1, r);
  return 0;
}

int main() {
  int N, K;
  scanf("%d", &N);
  scanf("%d", &K);
  int m = 0;
  for (int i = 0; i < N; i++) {
    scanf("%d", &seq[i]);
    m = MAX(seq[i], m);
  }
  build(1, 0, m);
  dp[0] = 1;
  modify(1, seq[0], dp[0]);
  int res = 0;
  for (int i = 1; i < N; i++) {
    dp[i] = search(1, seq[i] - K, seq[i] + K) + 1;
    modify(1, seq[i], dp[i]);
    if (dp[i] > res)
      res = dp[i];
  }
  printf("%d", res);
}

#include "stdio.h"

#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))

#define INF 300002

struct segtree {
  int l;
  int r;
  int max;
} tree[300010 * 4];

int dp[300010];
int seq[300010];

int modify(int i, int dis, int val) {
  if (tree[i].l == tree[i].r) {
    tree[i].max = val;
    return 0;
  }
  int mid = (tree[i].l + tree[i].r) >> 1;
  if (dis > mid)
    modify(2 * i + 1, dis, val);
  else
    modify(2 * i, dis, val);
  if (tree[i].max < val)
    tree[i].max = val;
  return 0;
}

int search(int i, int l, int r) {
  if (tree[i].l >= l && tree[i].r <= r)
    return tree[i].max;
  int m = (tree[i].l + tree[i].r) >> 1;
  int x = 0, y = 0;
  if (m >= l)
    x = search(i * 2, l, r);
  if (m < r)
    y = search(i * 2 + 1, l, r);
  return MAX(x, y);
}

int build(int i, int l, int r) {
  tree[i].l = l;
  tree[i].r = r;
  tree[i].max = 0;
  if (l == r)
    return 0;
  int mid = (l + r) >> 1;
  build(2 * i, l, mid);
  build(2 * i + 1, mid + 1, r);
  return 0;
}

int main() {
  int N, K;
  scanf("%d", &N);
  scanf("%d", &K);
  int max = 0, min = INF;
  for (int i = 0; i < N; i++) {
    scanf("%d", &seq[i]);
    max = MAX(seq[i], max);
    min = MIN(seq[i], min);
  }
  build(1, min, max);
  dp[0] = 1;
  modify(1, seq[0], dp[0]);
  int res = 0;
  for (int i = 1; i < N; i++) {
    dp[i] = search(1, seq[i] - K, seq[i] + K) + 1;
    modify(1, seq[i], dp[i]);
    if (dp[i] > res)
      res = dp[i];
  }
  printf("%d", res);
}


#include <bits/stdc++.h>
using namespace std;
// type alias
typedef long long LL;
typedef pair<int, int> II;
typedef tuple<int, int, int> III;
typedef vector<int> VI;
typedef vector<string> VS;
typedef unordered_map<int, int> MAPII;
typedef unordered_set<int> SETI;
template <class T> using VV = vector<vector<T>>;
// minmax
template <class T> inline T SMIN(T &a, const T b) {
  return a = (a > b) ? b : a;
}
template <class T> inline T SMAX(T &a, const T b) {
  return a = (a < b) ? b : a;
}
// repetition
#define FORE(i, a, b) for (int i = (a); i <= (b); ++i)
#define REPE(i, n) for (int i = 0; i <= (n); ++i)
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) for (int i = 0; i < (n); ++i)
#define FORR(x, arr) for (auto &x : arr)
#define SZ(a) int((a).size())
// collection
#define ALL(c) (c).begin(), (c).end()
// DP
#define MINUS(dp) memset(dp, -1, sizeof(dp))
#define ZERO(dp) memset(dp, 0, sizeof(dp))
// stdout
#define println(args...) fprintf(stdout, ##args), putchar('\\n');
// debug cerr
template <class Iter> void __kumaerrc(Iter begin, Iter end) {
  for (; begin != end; ++begin) {
    cerr << *begin << ',';
  }
  cerr << endl;
}
void __kumaerr(istream_iterator<string> it) {
  (void)it;
  cerr << endl;
}
template <typename T, typename... Args>
void __kumaerr(istream_iterator<string> it, T a, Args... args) {
  cerr << *it << "=" << a << ", ", __kumaerr(++it, args...);
}
template <typename S, typename T>
std::ostream &operator<<(std::ostream &_os, const std::pair<S, T> &_p) {
  return _os << "{" << _p.first << ',' << _p.second << "}";
}
#define __KUMATRACE__ true
#ifdef __KUMATRACE__
#define dump(args...)                                                          \\
  {                                                                            \\
    string _s = #args;                                                         \\
    replace(_s.begin(), _s.end(), ',', ' ');                                   \\
    stringstream _ss(_s);                                                      \\
    istream_iterator<string> _it(_ss);                                         \\
    __kumaerr(_it, args);                                                      \\
  }
#define dumpc(ar)                                                              \\
  {                                                                            \\
    cerr << #ar << ": ";                                                       \\
    FORR(x, (ar)) { cerr << x << ','; }                                        \\
    cerr << endl;                                                              \\
  }
#define dumpC(beg, end)                                                        \\
  {                                                                            \\
    cerr << "~" << #end << ": ";                                               \\
    __kumaerrc(beg, end);                                                      \\
  }
#else
#define dump(args...)
#define dumpc(ar)
#define dumpC(beg, end)
#endif
template <typename Val> struct SegmentTree {
  int N_; // adjusted N
  vector<Val> tree;
  Val id;
  using Merge = function<Val(Val, Val)>;
  Merge merge;

public:
  SegmentTree(int N, Val id, Merge merge) { prep(N, id, merge); }
  SegmentTree(vector<Val> A, Val id, Merge merge) {
    prep(A.size(), id, merge), this->build(A);
  }
  SegmentTree &prep(int N, Val id, Merge merge) {
    this->id = id, this->merge = merge;
    int n = 1;
    while (n < N)
      n <<= 1; // Init by power of 2
    this->tree = vector<Val>(2 * n - 1, id), this->N_ = n;
    return *this;
  }
  void build(const vector<Val> &ns) {
    for (int i = 0; i < ns.size(); ++i)
      tree[i + N_ - 1] = ns[i];
    for (int i = N_ - 2; i >= 0; --i)
      mergeAt(i);
  } // Initialize tree with `ns`
  void update(int i, const Val &x) {
    i += N_ - 1, tree[i] = x;
    while (i > 0)
      i = (i - 1) / 2, tree[i] = mergeAt(i);
  } // Update k-th (0-indexed) value
  Val query(int ql, int qr) {
    return queryTree(ql, qr, 0, 0, N_);
  } // query in range [ql,qr)
private:
  Val mergeAt(int i) {
    return tree[i] = merge(tree[2 * i + 1], tree[2 * i + 2]);
  }
  Val queryTree(const int ql, const int qr, int i, int tl, int tr) {
    if (tr <= ql || qr <= tl)
      return id; // out of range
    if (ql <= tl && tr <= qr)
      return tree[i];             // all covered
    int mid = tl + (tr - tl) / 2; // partially covered
    return merge(queryTree(ql, qr, 2 * i + 1, tl, mid),
                 queryTree(ql, qr, 2 * i + 2, mid, tr));
  }
};
template <typename Val> auto makeRMQ(vector<Val> A, Val id) {
  return SegmentTree<Val>(A, id, [](Val a, Val b) { return max(a, b); });
}
// $ cp-batch FlatSubsequence | diff FlatSubsequence.out -
// $ g++ -std=c++14 -Wall -O2 -D_GLIBCXX_DEBUG -fsanitize=address
// FlatSubsequence.cpp && ./a.out

/*

 9/26/2020

 5:06-

 */

const int MAX_N = 1e6 + 1;
int A[MAX_N];
int N, K;

void solve() {
  VI fake(N, 0);
  auto rmq = makeRMQ(fake, (int)0);
  int res = 0;
  REP(i, N) {
    int a = A[i];
    int ans = rmq.query(a - K, a + K + 1) + 1;
    SMAX(res, ans);
    rmq.update(a, ans);
  }
  cout << res << endl;
}

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout << setprecision(12) << fixed;

  cin >> N >> K;
  REP(i, N) cin >> A[i];
  solve();

  return 0;
}

#include <bits/stdc++.h>
using namespace std;
// type alias
typedef long long LL;
typedef pair<int, int> II;
typedef tuple<int, int, int> III;
typedef vector<int> VI;
typedef vector<string> VS;
typedef unordered_map<int, int> MAPII;
typedef unordered_set<int> SETI;
template <class T> using VV = vector<vector<T>>;
// minmax
template <class T> inline T SMIN(T &a, const T b) {
  return a = (a > b) ? b : a;
}
template <class T> inline T SMAX(T &a, const T b) {
  return a = (a < b) ? b : a;
}
// repetition
#define FORE(i, a, b) for (int i = (a); i <= (b); ++i)
#define REPE(i, n) for (int i = 0; i <= (n); ++i)
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) for (int i = 0; i < (n); ++i)
#define FORR(x, arr) for (auto &x : arr)
#define SZ(a) int((a).size())
// collection
#define ALL(c) (c).begin(), (c).end()
// DP
#define MINUS(dp) memset(dp, -1, sizeof(dp))
#define ZERO(dp) memset(dp, 0, sizeof(dp))
// stdout
#define println(args...) fprintf(stdout, ##args), putchar('\\n');
// debug cerr
template <class Iter> void __kumaerrc(Iter begin, Iter end) {
  for (; begin != end; ++begin) {
    cerr << *begin << ',';
  }
  cerr << endl;
}
void __kumaerr(istream_iterator<string> it) {
  (void)it;
  cerr << endl;
}
template <typename T, typename... Args>
void __kumaerr(istream_iterator<string> it, T a, Args... args) {
  cerr << *it << "=" << a << ", ", __kumaerr(++it, args...);
}
template <typename S, typename T>
std::ostream &operator<<(std::ostream &_os, const std::pair<S, T> &_p) {
  return _os << "{" << _p.first << ',' << _p.second << "}";
}
#define __KUMATRACE__ true
#ifdef __KUMATRACE__
#define dump(args...)                                                          \\
  {                                                                            \\
    string _s = #args;                                                         \\
    replace(_s.begin(), _s.end(), ',', ' ');                                   \\
    stringstream _ss(_s);                                                      \\
    istream_iterator<string> _it(_ss);                                         \\
    __kumaerr(_it, args);                                                      \\
  }
#define dumpc(ar)                                                              \\
  {                                                                            \\
    cerr << #ar << ": ";                                                       \\
    FORR(x, (ar)) { cerr << x << ','; }                                        \\
    cerr << endl;                                                              \\
  }
#define dumpC(beg, end)                                                        \\
  {                                                                            \\
    cerr << "~" << #end << ": ";                                               \\
    __kumaerrc(beg, end);                                                      \\
  }
#else
#define dump(args...)
#define dumpc(ar)
#define dumpC(beg, end)
#endif
template <typename Val> struct SegmentTree {
  int N_; // adjusted N
  vector<Val> tree;
  Val id;
  using Merge = function<Val(Val, Val)>;
  Merge merge;

public:
  SegmentTree(int N, Val id, Merge merge) { prep(N, id, merge); }
  SegmentTree(vector<Val> A, Val id, Merge merge) {
    prep(A.size(), id, merge), this->build(A);
  }
  SegmentTree &prep(int N, Val id, Merge merge) {
    this->id = id, this->merge = merge;
    int n = 1;
    while (n < N)
      n <<= 1; // Init by power of 2
    this->tree = vector<Val>(2 * n - 1, id), this->N_ = n;
    return *this;
  }
  void build(const vector<Val> &ns) {
    for (int i = 0; i < ns.size(); ++i)
      tree[i + N_ - 1] = ns[i];
    for (int i = N_ - 2; i >= 0; --i)
      mergeAt(i);
  } // Initialize tree with `ns`
  void update(int i, const Val &x) {
    i += N_ - 1, tree[i] = x;
    while (i > 0)
      i = (i - 1) / 2, tree[i] = mergeAt(i);
  } // Update k-th (0-indexed) value
  Val query(int ql, int qr) {
    return queryTree(ql, qr, 0, 0, N_);
  } // query in range [ql,qr)
private:
  Val mergeAt(int i) {
    return tree[i] = merge(tree[2 * i + 1], tree[2 * i + 2]);
  }
  Val queryTree(const int ql, const int qr, int i, int tl, int tr) {
    if (tr <= ql || qr <= tl)
      return id; // out of range
    if (ql <= tl && tr <= qr)
      return tree[i];             // all covered
    int mid = tl + (tr - tl) / 2; // partially covered
    return merge(queryTree(ql, qr, 2 * i + 1, tl, mid),
                 queryTree(ql, qr, 2 * i + 2, mid, tr));
  }
};
template <typename Val> auto makeRMQ(vector<Val> A, Val id) {
  return SegmentTree<Val>(A, id, [](Val a, Val b) { return max(a, b); });
}
// $ cp-batch FlatSubsequence | diff FlatSubsequence.out -
// $ g++ -std=c++14 -Wall -O2 -D_GLIBCXX_DEBUG -fsanitize=address
// FlatSubsequence.cpp && ./a.out

/*

 9/26/2020

 5:06-5:26

 */

const int MAX_N = 1e6 + 1;
int A[MAX_N];
int N, K;

void solve() {
  VI fake(MAX_N, 0);
  auto rmq = makeRMQ(fake, (int)0);
  int res = 0;
  REP(i, N) {
    int a = A[i];
    int ans = rmq.query(a - K, a + K + 1) + 1;
    SMAX(res, ans);
    rmq.update(a, ans);
  }
  cout << res << endl;
}

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout << setprecision(12) << fixed;

  cin >> N >> K;
  REP(i, N) cin >> A[i];
  solve();

  return 0;
}


// includes
#include <bits/stdc++.h>
using namespace std;

// macros
#define pb emplace_back
#define mk make_pair
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define rep(i, n) FOR(i, 0, n)
#define rrep(i, n) for (int i = ((int)(n)-1); i >= 0; i--)
#define irep(itr, st) for (auto itr = (st).begin(); itr != (st).end(); ++itr)
#define irrep(itr, st) for (auto itr = (st).rbegin(); itr != (st).rend(); ++itr)
#define whole(x) (x).begin(), (x).end()
#define sz(x) ((int)(x).size())
#define bit(n) (1LL << (n))
#define F first
#define S second
// functions
template <typename T> void unique(T &c) {
  c.erase(std::unique(c.begin(), c.end()), c.end());
}
template <class T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> bool chmin(T &a, const T &b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
template <typename T> istream &operator>>(istream &is, vector<T> &vec) {
  for (auto &v : vec)
    is >> v;
  return is;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
  for (int i = 0; i < vec.size(); i++) {
    os << vec[i];
    if (i + 1 != vec.size())
      os << " ";
  }
  return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &st) {
  for (auto itr = st.begin(); itr != st.end(); ++itr) {
    os << *itr;
    auto titr = itr;
    if (++titr != st.end())
      os << " ";
  }
  return os;
}
template <typename T>
ostream &operator<<(ostream &os, const unordered_set<T> &st) {
  for (auto itr = st.begin(); itr != st.end(); ++itr) {
    os << *itr;
    auto titr = itr;
    if (++titr != st.end())
      os << " ";
  }
  return os;
}
template <typename T> ostream &operator<<(ostream &os, const multiset<T> &st) {
  for (auto itr = st.begin(); itr != st.end(); ++itr) {
    os << *itr;
    auto titr = itr;
    if (++titr != st.end())
      os << " ";
  }
  return os;
}
template <typename T>
ostream &operator<<(ostream &os, const unordered_multiset<T> &st) {
  for (auto itr = st.begin(); itr != st.end(); ++itr) {
    os << *itr;
    auto titr = itr;
    if (++titr != st.end())
      os << " ";
  }
  return os;
}
template <typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
  os << "(" << p.first << ", " << p.second << ")";
  return os;
}
template <typename T1, typename T2>
ostream &operator<<(ostream &os, const map<T1, T2> &mp) {
  for (auto itr = mp.begin(); itr != mp.end(); ++itr) {
    os << "(" << itr->first << ", " << itr->second << ")";
    auto titr = itr;
    if (++titr != mp.end())
      os << " ";
  }
  return os;
}
template <typename T1, typename T2>
ostream &operator<<(ostream &os, const unordered_map<T1, T2> &mp) {
  for (auto itr = mp.begin(); itr != mp.end(); ++itr) {
    os << "(" << itr->first << ", " << itr->second << ")";
    auto titr = itr;
    if (++titr != mp.end())
      os << " ";
  }
  return os;
}
//  types
using ll = long long int;
using P = pair<int, int>;
// constants
const int inf = 1e9;
const ll linf = 1LL << 60;
const double EPS = 1e-10;
const int mod = 1000000007;
const int dx[4] = {-1, 0, 1, 0};
const int dy[4] = {0, -1, 0, 1};
// io
struct fast_io {
  fast_io() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(20);
  }
} fast_io_;

template <class Monoid> class SegmentTree {
public:
  int n;
  using T = typename Monoid::value_type;
  vector<T> val;
  T identity;

  SegmentTree() {}
  SegmentTree(int n_, vector<T> v = vector<T>()) {
    n = 1;
    while (n < n_)
      n *= 2;
    identity = Monoid::identity;
    val.assign(2 * n - 1, identity);

    for (size_t i = 0; i < v.size(); i++) {
      val[i + n - 1] = v[i];
    }
    for (int i = n - 2; i >= 0; i--) {
      val[i] = Monoid::operation(val[2 * i + 1], val[2 * i + 2]);
    }
  }
  void update(int k, const T &t) {
    k = k + n - 1;
    val[k] = t;
    while (k > 0) {
      k = (k - 1) / 2;
      val[k] = Monoid::operation(val[2 * k + 1], val[2 * k + 2]);
    }
  }
  T query(int a, int b, int k, int l, int r) {
    if (r <= a || b <= l)
      return identity;
    if (a <= l && r <= b)
      return val[k];
    T lv = query(a, b, 2 * k + 1, l, (l + r) / 2);
    T rv = query(a, b, 2 * k + 2, (l + r) / 2, r);
    return Monoid::operation(lv, rv);
  }
  T query(int a, int b) { return query(a, b, 0, 0, n); }
  T get(int i) { return val[i + n - 1]; }
};

template <typename T> class RMQ {
public:
  const static T identity;
  using value_type = T;

  RMQ() {}
  static T operation(T &l, T &r) { return max(l, r); }
};

template <typename T> const T RMQ<T>::identity = numeric_limits<T>::min();

const int B = 300010;

int main(int argc, char const *argv[]) {
  int n, k;
  cin >> n >> k;
  vector<int> a(n);
  cin >> a;
  SegmentTree<RMQ<int>> seg(n);
  int res = 0;
  rep(i, n) {
    int l = max(0, a[i] - k);
    int r = min(a[i] + k, B - 1);
    int p = seg.query(l, r + 1);
    if (p == seg.identity)
      p = 0;
    p++;
    seg.update(a[i], p);
    chmax(res, p);
  }
  cout << res << endl;
  return 0;
}

// includes
#include <bits/stdc++.h>
using namespace std;

// macros
#define pb emplace_back
#define mk make_pair
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define rep(i, n) FOR(i, 0, n)
#define rrep(i, n) for (int i = ((int)(n)-1); i >= 0; i--)
#define irep(itr, st) for (auto itr = (st).begin(); itr != (st).end(); ++itr)
#define irrep(itr, st) for (auto itr = (st).rbegin(); itr != (st).rend(); ++itr)
#define whole(x) (x).begin(), (x).end()
#define sz(x) ((int)(x).size())
#define bit(n) (1LL << (n))
#define F first
#define S second
// functions
template <typename T> void unique(T &c) {
  c.erase(std::unique(c.begin(), c.end()), c.end());
}
template <class T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> bool chmin(T &a, const T &b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
template <typename T> istream &operator>>(istream &is, vector<T> &vec) {
  for (auto &v : vec)
    is >> v;
  return is;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
  for (int i = 0; i < vec.size(); i++) {
    os << vec[i];
    if (i + 1 != vec.size())
      os << " ";
  }
  return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &st) {
  for (auto itr = st.begin(); itr != st.end(); ++itr) {
    os << *itr;
    auto titr = itr;
    if (++titr != st.end())
      os << " ";
  }
  return os;
}
template <typename T>
ostream &operator<<(ostream &os, const unordered_set<T> &st) {
  for (auto itr = st.begin(); itr != st.end(); ++itr) {
    os << *itr;
    auto titr = itr;
    if (++titr != st.end())
      os << " ";
  }
  return os;
}
template <typename T> ostream &operator<<(ostream &os, const multiset<T> &st) {
  for (auto itr = st.begin(); itr != st.end(); ++itr) {
    os << *itr;
    auto titr = itr;
    if (++titr != st.end())
      os << " ";
  }
  return os;
}
template <typename T>
ostream &operator<<(ostream &os, const unordered_multiset<T> &st) {
  for (auto itr = st.begin(); itr != st.end(); ++itr) {
    os << *itr;
    auto titr = itr;
    if (++titr != st.end())
      os << " ";
  }
  return os;
}
template <typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
  os << "(" << p.first << ", " << p.second << ")";
  return os;
}
template <typename T1, typename T2>
ostream &operator<<(ostream &os, const map<T1, T2> &mp) {
  for (auto itr = mp.begin(); itr != mp.end(); ++itr) {
    os << "(" << itr->first << ", " << itr->second << ")";
    auto titr = itr;
    if (++titr != mp.end())
      os << " ";
  }
  return os;
}
template <typename T1, typename T2>
ostream &operator<<(ostream &os, const unordered_map<T1, T2> &mp) {
  for (auto itr = mp.begin(); itr != mp.end(); ++itr) {
    os << "(" << itr->first << ", " << itr->second << ")";
    auto titr = itr;
    if (++titr != mp.end())
      os << " ";
  }
  return os;
}
//  types
using ll = long long int;
using P = pair<int, int>;
// constants
const int inf = 1e9;
const ll linf = 1LL << 60;
const double EPS = 1e-10;
const int mod = 1000000007;
const int dx[4] = {-1, 0, 1, 0};
const int dy[4] = {0, -1, 0, 1};
// io
struct fast_io {
  fast_io() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(20);
  }
} fast_io_;

template <class Monoid> class SegmentTree {
public:
  int n;
  using T = typename Monoid::value_type;
  vector<T> val;
  T identity;

  SegmentTree() {}
  SegmentTree(int n_, vector<T> v = vector<T>()) {
    n = 1;
    while (n < n_)
      n *= 2;
    identity = Monoid::identity;
    val.assign(2 * n - 1, identity);

    for (size_t i = 0; i < v.size(); i++) {
      val[i + n - 1] = v[i];
    }
    for (int i = n - 2; i >= 0; i--) {
      val[i] = Monoid::operation(val[2 * i + 1], val[2 * i + 2]);
    }
  }
  void update(int k, const T &t) {
    k = k + n - 1;
    val[k] = t;
    while (k > 0) {
      k = (k - 1) / 2;
      val[k] = Monoid::operation(val[2 * k + 1], val[2 * k + 2]);
    }
  }
  T query(int a, int b, int k, int l, int r) {
    if (r <= a || b <= l)
      return identity;
    if (a <= l && r <= b)
      return val[k];
    T lv = query(a, b, 2 * k + 1, l, (l + r) / 2);
    T rv = query(a, b, 2 * k + 2, (l + r) / 2, r);
    return Monoid::operation(lv, rv);
  }
  T query(int a, int b) { return query(a, b, 0, 0, n); }
  T get(int i) { return val[i + n - 1]; }
};

template <typename T> class RMQ {
public:
  const static T identity;
  using value_type = T;

  RMQ() {}
  static T operation(T &l, T &r) { return max(l, r); }
};

template <typename T> const T RMQ<T>::identity = numeric_limits<T>::min();

const int B = 300010;

int main(int argc, char const *argv[]) {
  int n, k;
  cin >> n >> k;
  vector<int> a(n);
  cin >> a;
  SegmentTree<RMQ<int>> seg(B);
  int res = 0;
  rep(i, n) {
    int l = max(0, a[i] - k);
    int r = min(a[i] + k, B - 1);
    int p = seg.query(l, r + 1);
    if (p == seg.identity)
      p = 0;
    p++;
    seg.update(a[i], p);
    chmax(res, p);
  }
  cout << res << endl;
  return 0;
}