#include <algorithm>
#include <array>
#include <assert.h>
#include <bitset>
#include <cctype>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstdlib>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <utility>

using namespace std;
typedef long long ll;
using ull = unsigned long long;

template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
template <typename T> T gcd(T a, T b) {
  a = abs(a), b = abs(b);
  while (b > 0) {
    tie(a, b) = make_pair(b, a % b);
  }
  return a;
}
// mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());

constexpr long long INF = 1LL << 60;
constexpr int inf = 1000000007;
// constexpr long long mod = 1000000007LL;
constexpr long long mod = 998244353;
constexpr int MAX = 5000000;

int f(int a, int b) { return max(a, b); }
template <typename Monoid> struct SegmentTree {
  // using F = function< Monoid(Monoid, Monoid) >;

  int sz;
  vector<Monoid> seg;

  // const F f;
  const Monoid M1;

  SegmentTree(int n, /*const F f,*/ const Monoid &M1) : /*f(f),*/ M1(M1) {
    sz = 1;
    while (sz < n)
      sz <<= 1;
    seg.assign(2 * sz, M1);
  }

  void set(int k, const Monoid &x) { seg[k + sz] = x; }

  void build() {
    for (int k = sz - 1; k > 0; k--) {
      seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]);
    }
  }

  void update(int k, const Monoid &x) {
    k += sz;
    seg[k] = x;
    while (k >>= 1) {
      seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]);
    }
  }

  Monoid query(int a, int b) {
    Monoid L = M1, R = M1;
    if (a >= b)
      return M1;
    for (a += sz, b += sz; a < b; a >>= 1, b >>= 1) {
      if (a & 1)
        L = f(L, seg[a++]);
      if (b & 1)
        R = f(seg[--b], R);
    }
    return f(L, R);
  }
};

int main() {

  cin.tie(nullptr);
  ios::sync_with_stdio(false);

  int n, k;
  cin >> n >> k;
  vector<int> a(n);
  for (int i = 0; i < n; i++)
    cin >> a[i];
  vector<int> dp(n + 1);
  SegmentTree<int> seg(n, -inf);
  for (int i = 0; i < n; i++) {
    {
      int req = a[i] - k;
      int idx = seg.query(req, a[i] + 1);
      if (idx >= 0)
        chmax(dp[i + 1], dp[idx + 1] + 1);
    }
    {
      int req = a[i] + k;
      int idx = seg.query(a[i], req + 1);
      if (idx >= 0)
        chmax(dp[i + 1], dp[idx + 1] + 1);
    }
    chmax(dp[i + 1], 1);
    seg.update(a[i], i);
  }
  cout << dp[n] << endl;
  return 0;
}

#include <algorithm>
#include <array>
#include <assert.h>
#include <bitset>
#include <cctype>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstdlib>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <utility>

using namespace std;
typedef long long ll;
using ull = unsigned long long;

template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
template <typename T> T gcd(T a, T b) {
  a = abs(a), b = abs(b);
  while (b > 0) {
    tie(a, b) = make_pair(b, a % b);
  }
  return a;
}
// mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());

constexpr long long INF = 1LL << 60;
constexpr int inf = 1000000007;
// constexpr long long mod = 1000000007LL;
constexpr long long mod = 998244353;
constexpr int MAX = 5000000;

int f(int a, int b) { return max(a, b); }
template <typename Monoid> struct SegmentTree {
  // using F = function< Monoid(Monoid, Monoid) >;

  int sz;
  vector<Monoid> seg;

  // const F f;
  const Monoid M1;

  SegmentTree(int n, /*const F f,*/ const Monoid &M1) : /*f(f),*/ M1(M1) {
    sz = 1;
    while (sz < n)
      sz <<= 1;
    seg.assign(2 * sz, M1);
  }

  void set(int k, const Monoid &x) { seg[k + sz] = x; }

  void build() {
    for (int k = sz - 1; k > 0; k--) {
      seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]);
    }
  }

  void update(int k, const Monoid &x) {
    k += sz;
    seg[k] = x;
    while (k >>= 1) {
      seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]);
    }
  }

  Monoid query(int a, int b) {
    Monoid L = M1, R = M1;
    if (a >= b)
      return M1;
    for (a += sz, b += sz; a < b; a >>= 1, b >>= 1) {
      if (a & 1)
        L = f(L, seg[a++]);
      if (b & 1)
        R = f(seg[--b], R);
    }
    return f(L, R);
  }
};

int main() {

  cin.tie(nullptr);
  ios::sync_with_stdio(false);

  int n, k;
  cin >> n >> k;
  vector<int> a(n);
  for (int i = 0; i < n; i++)
    cin >> a[i];
  vector<int> dp(n + 1);
  SegmentTree<int> seg(MAX, -inf);
  for (int i = 0; i < n; i++) {
    {
      int req = max(a[i] - k, 0);
      int idx = seg.query(req, a[i] + 1);
      if (idx >= 0)
        chmax(dp[i + 1], dp[idx + 1] + 1);
    }
    {
      int req = a[i] + k;
      int idx = seg.query(a[i], req + 1);
      if (idx >= 0)
        chmax(dp[i + 1], dp[idx + 1] + 1);
    }
    chmax(dp[i + 1], 1);
    seg.update(a[i], i);
  }
  cout << *max_element(dp.begin(), dp.end()) << endl;
  return 0;
}


#include <bits/stdc++.h>

#define rep(i, n) for (int i = 0; i < (n); i++)
#define rrep(i, n) for (int i = (n)-1; i >= 0; i--)
#define rep1(i, n) for (int i = 1; i <= (n); i++)
#define rrep1(i, n) for (int i = (n); i > 0; i--)

#define ll long long
#define pi pair<int, int>
#define pll pair<ll, ll>

#define MOD 1000000007
#define INF 1000000000000000LL

using namespace std;

#define MAXN 660000

struct Seg {
  vector<ll> sum;
  vector<ll> mx;
  Seg() {
    sum.resize(1 << 29, 0);
    mx.resize(1 << 29, 0);
  }

  void add_val(ll l, ll r, ll val, ll bottom = 0, ll top = 1 << 28,
               ll pos = 1) {
    if (l <= bottom && top <= r) {
      sum[pos] += val;
      return;
    }
    if (r <= bottom || l >= top)
      return;

    ll mid = (bottom + top) / 2;
    add_val(l, r, val, bottom, mid, pos * 2);
    add_val(l, r, val, mid, top, pos * 2 + 1);
    mx[pos] =
        max<ll>(mx[pos * 2] + sum[pos * 2], mx[pos * 2 + 1] + sum[pos * 2 + 1]);
  }

  ll max_val(ll l, ll r, ll bottom = 0, ll top = 1 << 28, ll pos = 1) {
    if (l <= bottom && top <= r)
      return sum[pos] + mx[pos];
    if (r <= bottom || l >= top)
      return -INF;

    ll mid = (bottom + top) / 2;
    return max<ll>(max_val(l, r, bottom, mid, pos * 2),
                   max_val(l, r, mid, top, pos * 2 + 1)) +
           sum[pos];
  }
};

int main() {
  int n, k;
  cin >> n >> k;
  vector<int> a(n);
  rep(i, n) cin >> a[i];

  Seg seg;
  int result = 0;
  rep(i, n) {
    ll l = max(0, a[i] - k);
    ll r = a[i] + k + 1;
    ll mx = seg.max_val(l, r);
    ll cv = seg.max_val(a[i], a[i] + 1);
    seg.add_val(a[i], a[i] + 1, mx + 1 - cv);
  }

  cout << seg.max_val(1, MAXN);

  return 0;
}

#include <bits/stdc++.h>

#define rep(i, n) for (int i = 0; i < (n); i++)
#define rrep(i, n) for (int i = (n)-1; i >= 0; i--)
#define rep1(i, n) for (int i = 1; i <= (n); i++)
#define rrep1(i, n) for (int i = (n); i > 0; i--)

#define ll long long
#define pi pair<int, int>
#define pll pair<ll, ll>

#define MOD 1000000007
#define INF 1000000000000000LL

using namespace std;

#define MAXN 660000

struct Seg {
  vector<ll> sum;
  vector<ll> mx;
  Seg() {
    sum.resize(1 << 23, 0);
    mx.resize(1 << 23, 0);
  }

  void add_val(ll l, ll r, ll val, ll bottom = 0, ll top = 1 << 22,
               ll pos = 1) {
    if (l <= bottom && top <= r) {
      sum[pos] += val;
      return;
    }
    if (r <= bottom || l >= top)
      return;

    ll mid = (bottom + top) / 2;
    add_val(l, r, val, bottom, mid, pos * 2);
    add_val(l, r, val, mid, top, pos * 2 + 1);
    mx[pos] =
        max<ll>(mx[pos * 2] + sum[pos * 2], mx[pos * 2 + 1] + sum[pos * 2 + 1]);
  }

  ll max_val(ll l, ll r, ll bottom = 0, ll top = 1 << 22, ll pos = 1) {
    if (l <= bottom && top <= r)
      return sum[pos] + mx[pos];
    if (r <= bottom || l >= top)
      return -INF;

    ll mid = (bottom + top) / 2;
    return max<ll>(max_val(l, r, bottom, mid, pos * 2),
                   max_val(l, r, mid, top, pos * 2 + 1)) +
           sum[pos];
  }
};

int main() {
  int n, k;
  cin >> n >> k;
  vector<int> a(n);
  rep(i, n) cin >> a[i];

  Seg seg;
  rep(i, n) {
    ll l = max(0, a[i] - k);
    ll r = a[i] + k + 1;
    ll mx = seg.max_val(l, r);
    ll cv = seg.max_val(a[i], a[i] + 1);
    seg.add_val(a[i], a[i] + 1, mx + 1 - cv);
  }

  cout << seg.max_val(1, MAXN);

  return 0;
}

terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc


#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
#define repr(i, a, b) for (int i = a; i < b; i++)
#define rep(i, n) for (int i = 0; i < n; i++)
#define invrepr(i, a, b) for (int i = b - 1; i >= a; i--)
#define invrep(i, n) invrepr(i, 0, n)
#define repitr(itr, a) for (auto itr = a.begin(); itr != a.end(); ++itr)
#define P pair<int, int>
const ll MOD = 1e9 + 7;
const int MAX = 1e5 + 10;
const ll INF = (1LL << 31) - 1;
const double PI = acos(-1);

const int SEGLEN = 1 << 18;
vector<int> segtree(2 * SEGLEN);

void update(int ind, int x) {
  ind += SEGLEN;
  segtree[ind] = x;
  while (1) {
    ind /= 2;
    if (ind == 0)
      break;
    segtree[ind] = max(segtree[2 * ind], segtree[2 * ind + 1]);
  }
}

int get_max(int l, int r) {
  l += SEGLEN;
  r += SEGLEN;
  int ans = 0;
  while (l < r) {
    if (l % 2 == 1) {
      ans = max(ans, segtree[l]);
      ++l;
    }
    l /= 2;
    if (r % 2 == 1) {
      ans = max(ans, segtree[r - 1]);
      --r;
    }
    r /= 2;
  }

  return ans;
}

int main() {
  ios_base::sync_with_stdio(false);

  int n, k;
  cin >> n >> k;
  rep(i, n) {
    int a;
    cin >> a;
    int s = max(0, a - k), t = min(SEGLEN, a + k + 1);
    update(a, get_max(s, t) + 1);
  }
  int ans = 1;
  rep(i, SEGLEN) ans = max(ans, segtree[i + SEGLEN]);
  cout << ans << endl;

  return 0;
}

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
#define repr(i, a, b) for (int i = a; i < b; i++)
#define rep(i, n) for (int i = 0; i < n; i++)
#define invrepr(i, a, b) for (int i = b - 1; i >= a; i--)
#define invrep(i, n) invrepr(i, 0, n)
#define repitr(itr, a) for (auto itr = a.begin(); itr != a.end(); ++itr)
#define P pair<int, int>
const ll MOD = 1e9 + 7;
const int MAX = 1e5 + 10;
const ll INF = (1LL << 31) - 1;
const double PI = acos(-1);

const int SEGLEN = 1 << 19;
vector<int> segtree(2 * SEGLEN);

void update(int ind, int x) {
  ind += SEGLEN;
  segtree[ind] = x;
  while (1) {
    ind /= 2;
    if (ind == 0)
      break;
    segtree[ind] = max(segtree[2 * ind], segtree[2 * ind + 1]);
  }
}

int get_max(int l, int r) {
  l += SEGLEN;
  r += SEGLEN;
  int ans = 0;
  while (l < r) {
    if (l % 2 == 1) {
      ans = max(ans, segtree[l]);
      ++l;
    }
    l /= 2;
    if (r % 2 == 1) {
      ans = max(ans, segtree[r - 1]);
      --r;
    }
    r /= 2;
  }

  return ans;
}

int main() {
  ios_base::sync_with_stdio(false);
  int n, k;
  cin >> n >> k;
  rep(i, n) {
    int a;
    cin >> a;
    int s = max(0, a - k), t = min(SEGLEN, a + k + 1);
    update(a, get_max(s, t) + 1);
  }
  int ans = 1;
  rep(i, SEGLEN) ans = max(ans, segtree[i + SEGLEN]);
  cout << ans << endl;

  return 0;
}


#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, n) for (ll i = 0; i < n; ++i)
#define all(c) begin(c), end(c)
#define PI acos(-1)
#define oo LLONG_MAX
template <typename T1, typename T2> bool chmax(T1 &a, T2 b) {
  if (a < b) {
    a = b;
    return true;
  } else
    return false;
}
template <typename T1, typename T2> bool chmin(T1 &a, T2 b) {
  if (a > b) {
    a = b;
    return true;
  } else
    return false;
}
/*
とれるときにとるかどうか分岐
1 1
5 1
4 2
3 3
8 8-14のうちさいだいち
完全セグ木か
*/

int INF = -1e9;

struct SegmentTree {
private:
  int n;
  vector<int> node;

public:
  // 元配列 v をセグメント木で表現する
  SegmentTree(vector<int> v) {
    // 最下段のノード数は元配列のサイズ以上になる最小の 2 冪 -> これを n とおく
    // セグメント木全体で必要なノード数は 2n-1 個である
    int sz = v.size();
    n = 1;
    while (n < sz)
      n *= 2;
    node.resize(2 * n - 1, INF);

    // 最下段に値を入れたあとに、下の段から順番に値を入れる
    // 値を入れるには、自分の子の 2 値を参照すれば良い
    for (int i = 0; i < sz; i++)
      node[i + n - 1] = v[i];
    // ここでminを使うことで区間の最小値となる、最大にすれば最大値
    for (int i = n - 2; i >= 0; i--)
      node[i] = max(node[2 * i + 1], node[2 * i + 2]);
  }

  // x番目(0-indexed)の要素をvalにする
  void update(int x, int val) {
    // 最下段のノードにアクセスする
    x += (n - 1);

    // 最下段のノードを更新したら、あとは親に上って更新していく
    node[x] = val;
    while (x > 0) {
      x = (x - 1) / 2;
      // ここでminを使うことで区間の最小値となる、最大にすれば最大値
      node[x] = max(node[2 * x + 1], node[2 * x + 2]);
    }
  }

  // 要求区間 [a, b) 中の要素の最大値を答える(つまりbは含まれない)
  // k := 自分がいるノードのインデックス
  // 対象区間は [l, r) にあたる

  int getmax(int a, int b, int k = 0, int l = 0, int r = -1) {
    // 最初に呼び出されたときの対象区間は [0, n)
    if (r < 0)
      r = n;

    // 要求区間と対象区間が交わらない ->
    // 適当に返す(今回は最小値なので、結果に影響しないような大きい値を返しておく)
    if (r <= a || b <= l)
      return INF;

    // 要求区間が対象区間を完全に被覆 -> 対象区間を答えの計算に使う
    if (a <= l && r <= b)
      return node[k];

    // 要求区間が対象区間の一部を被覆 -> 子について探索を行う
    // 左側の子を vl ・ 右側の子を vr としている
    // 新しい対象区間は、現在の対象区間を半分に割ったもの
    int vl = getmax(a, b, 2 * k + 1, l, (l + r) / 2);
    int vr = getmax(a, b, 2 * k + 2, (l + r) / 2, r);
    return max(vl, vr);
  }

  // 要求区間 [a, b) 中の要素の最大値を答える(つまりbは含まれない)
  // k := 自分がいるノードのインデックス
  // 対象区間は [l, r) にあたる

  int getleft(int x, int val, int k = 0, int l = 0, int r = -1) {
    // 最初に呼び出されたときの対象区間は [0, n)
    if (r < 0)
      r = n;

    // 要求区間と対象区間が交わらない ->
    // 適当に返す(今回は最小値なので、結果に影響しないような大きい値を返しておく)
    if (r <= x || n <= l)
      return INF;

    // 要求区間が対象区間を完全に被覆 -> 対象区間を答えの計算に使う
    if (x <= l && r <= n) {
      if (k >= n - 1)
        return (node[k] >= val ? k - n + 2 : INF); // これ返る。
      if (getmax(l, (l + r) / 2) >= val)
        return (getleft(x, val, 2 * k + 1, l, (l + r) / 2)); // 先送り
      if (getmax((l + r) / 2, r) >= val)
        return (getleft(x, val, 2 * k + 2, (l + r) / 2, r)); // 先送り
      return (INF);
    }

    // 要求区間が対象区間の一部を被覆 -> 子について探索を行う
    // 左側の子を vl ・ 右側の子を vr としている
    // 新しい対象区間は、現在の対象区間を半分に割ったもの
    int vl = getleft(x, val, 2 * k + 1, l, (l + r) / 2);
    int vr = getleft(x, val, 2 * k + 2, (l + r) / 2, r);
    if (vl != INF)
      return (vl); // 部分から完全、とかいう、最後の判定がこれになることもある
    if (vr != INF)
      return (vr); // 最後の判定がこれになることもある
    return (INF);
  }
};

int main(void) {
  int n, k;
  cin >> n >> k;
  vector<int> a(n + 1);
  SegmentTree seg(a);
  for (int i = 0; i < n; i++) {
    int a;
    cin >> a;
    ll low = max(a - k, 0);
    ll high = min(a + k + 1, n);
    ll val = seg.getmax(low, high);
    // cout << "i:"<<i<<" a:"<<a<<" val:"<<val << " low:"<<low<<"
    // high:"<<high<<endl;
    seg.update(a, val + 1);
  }
  ll ans = seg.getmax(0, n);
  cout << ans << endl;
}

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, n) for (ll i = 0; i < n; ++i)
#define all(c) begin(c), end(c)
#define PI acos(-1)
#define oo LLONG_MAX
template <typename T1, typename T2> bool chmax(T1 &a, T2 b) {
  if (a < b) {
    a = b;
    return true;
  } else
    return false;
}
template <typename T1, typename T2> bool chmin(T1 &a, T2 b) {
  if (a > b) {
    a = b;
    return true;
  } else
    return false;
}
/*
とれるときにとるかどうか分岐
1 1
5 1
4 2
3 3
8 8-14のうちさいだいち
完全セグ木か
*/

int INF = -1e9;

struct SegmentTree {
private:
  int n;
  vector<int> node;

public:
  // 元配列 v をセグメント木で表現する
  SegmentTree(vector<int> v) {
    // 最下段のノード数は元配列のサイズ以上になる最小の 2 冪 -> これを n とおく
    // セグメント木全体で必要なノード数は 2n-1 個である
    int sz = v.size();
    n = 1;
    while (n < sz)
      n *= 2;
    node.resize(2 * n - 1, INF);

    // 最下段に値を入れたあとに、下の段から順番に値を入れる
    // 値を入れるには、自分の子の 2 値を参照すれば良い
    for (int i = 0; i < sz; i++)
      node[i + n - 1] = v[i];
    // ここでminを使うことで区間の最小値となる、最大にすれば最大値
    for (int i = n - 2; i >= 0; i--)
      node[i] = max(node[2 * i + 1], node[2 * i + 2]);
  }

  // x番目(0-indexed)の要素をvalにする
  void update(int x, int val) {
    // 最下段のノードにアクセスする
    x += (n - 1);

    // 最下段のノードを更新したら、あとは親に上って更新していく
    node[x] = val;
    while (x > 0) {
      x = (x - 1) / 2;
      // ここでminを使うことで区間の最小値となる、最大にすれば最大値
      node[x] = max(node[2 * x + 1], node[2 * x + 2]);
    }
  }

  // 要求区間 [a, b) 中の要素の最大値を答える(つまりbは含まれない)
  // k := 自分がいるノードのインデックス
  // 対象区間は [l, r) にあたる

  int getmax(int a, int b, int k = 0, int l = 0, int r = -1) {
    // 最初に呼び出されたときの対象区間は [0, n)
    if (r < 0)
      r = n;

    // 要求区間と対象区間が交わらない ->
    // 適当に返す(今回は最小値なので、結果に影響しないような大きい値を返しておく)
    if (r <= a || b <= l)
      return INF;

    // 要求区間が対象区間を完全に被覆 -> 対象区間を答えの計算に使う
    if (a <= l && r <= b)
      return node[k];

    // 要求区間が対象区間の一部を被覆 -> 子について探索を行う
    // 左側の子を vl ・ 右側の子を vr としている
    // 新しい対象区間は、現在の対象区間を半分に割ったもの
    int vl = getmax(a, b, 2 * k + 1, l, (l + r) / 2);
    int vr = getmax(a, b, 2 * k + 2, (l + r) / 2, r);
    return max(vl, vr);
  }

  // 要求区間 [a, b) 中の要素の最大値を答える(つまりbは含まれない)
  // k := 自分がいるノードのインデックス
  // 対象区間は [l, r) にあたる

  int getleft(int x, int val, int k = 0, int l = 0, int r = -1) {
    // 最初に呼び出されたときの対象区間は [0, n)
    if (r < 0)
      r = n;

    // 要求区間と対象区間が交わらない ->
    // 適当に返す(今回は最小値なので、結果に影響しないような大きい値を返しておく)
    if (r <= x || n <= l)
      return INF;

    // 要求区間が対象区間を完全に被覆 -> 対象区間を答えの計算に使う
    if (x <= l && r <= n) {
      if (k >= n - 1)
        return (node[k] >= val ? k - n + 2 : INF); // これ返る。
      if (getmax(l, (l + r) / 2) >= val)
        return (getleft(x, val, 2 * k + 1, l, (l + r) / 2)); // 先送り
      if (getmax((l + r) / 2, r) >= val)
        return (getleft(x, val, 2 * k + 2, (l + r) / 2, r)); // 先送り
      return (INF);
    }

    // 要求区間が対象区間の一部を被覆 -> 子について探索を行う
    // 左側の子を vl ・ 右側の子を vr としている
    // 新しい対象区間は、現在の対象区間を半分に割ったもの
    int vl = getleft(x, val, 2 * k + 1, l, (l + r) / 2);
    int vr = getleft(x, val, 2 * k + 2, (l + r) / 2, r);
    if (vl != INF)
      return (vl); // 部分から完全、とかいう、最後の判定がこれになることもある
    if (vr != INF)
      return (vr); // 最後の判定がこれになることもある
    return (INF);
  }
};

int main(void) {
  int n, k;
  cin >> n >> k;
  vector<int> a(300010);
  SegmentTree seg(a);
  for (int i = 0; i < n; i++) {
    int a;
    cin >> a; // indexとみなす
    ll low = max(a - k, 0);
    ll high = min(a + k + 1, 300001);
    ll val = seg.getmax(low, high);
    // cout << "i:"<<i<<" a:"<<a<<" val:"<<val << " low:"<<low<<"
    // high:"<<high<<endl;
    seg.update(a, val + 1);
  }
  ll ans = seg.getmax(0, 300001);
  cout << ans << endl;
}


#pragma GCC target("sse4.2")
#include <bits/stdc++.h>

using namespace std;

#define F first
#define S second
#define PB push_back
#define ln "\\n"
#define forn(i, e) for (ll i = 0; i < e; i++)
#define forsn(i, s, e) for (ll i = s; i < e; i++)
#define rforn(i, e) for (ll i = e; i >= 0; i--)
#define rforsn(i, e, s) for (ll i = e; i >= s; i--)
#define vasort(v) sort(v.begin(), v.end());
#define vdsort(v) sort(v.begin(), v.end(), greater<ll>());
#define fio                                                                    \\
  ios_base::sync_with_stdio(false);                                            \\
  cin.tie(NULL);                                                               \\
  cout.tie(NULL)
#define mem(a, b) memset(a, b, sizeof(a))
#define sz(x) ((int)size(x))
#define EB emplace_back
#define flush fflush(stdout)
#define out1(x1) cout << x1 << ln
#define out2(x1, x2) cout << x1 << " " << x2 << endl
#define out3(x1, x2, x3) cout << x1 << " " << x2 << " " << x3 << endl
#define out4(x1, x2, x3, x4)                                                   \\
  cout << x1 << " " << x2 << " " << x3 << " " << x4 << ln
#define all(d) d.begin(), d.end()
#define unordered_set(T) unordered_set<T, custom_hash>
#define unordered_map(T1, T2) unordered_map<T1, T2, custom_hash>

#define in1(x1) cin >> x1
#define in2(x1, x2) cin >> x1 >> x2
#define in3(x1, x2, x3) cin >> x1 >> x2 >> x3
#define in4(x1, x2, x3, x4) cin >> x1 >> x2 >> x3 >> x4

#define arrin(a, n) forn(i, n) cin >> a[i];
#define arrout(a, n)                                                           \\
  forn(i, n) { cout << a[i] << " "; }                                          \\
  cout << ln;

/* ---------------- IO ----------------*/

namespace IO {
const int BUFFER_SIZE = 1 << 15;
char input_buffer[BUFFER_SIZE];
int input_pos = 0, input_len = 0;
char output_buffer[BUFFER_SIZE];
int output_pos = 0;
char number_buffer[100];
uint8_t lookup[100];
void _update_input_buffer() {
  input_len = fread(input_buffer, sizeof(char), BUFFER_SIZE, stdin);
  input_pos = 0;
  if (input_len == 0)
    input_buffer[0] = EOF;
}
inline char next_char(bool advance = true) {
  if (input_pos >= input_len)
    _update_input_buffer();

  return input_buffer[advance ? input_pos++ : input_pos];
}

template <typename T> inline void read_int(T &number) {
  bool negative = false;
  number = 0;

  while (!isdigit(next_char(false)))
    if (next_char() == '-')
      negative = true;

  do {
    number = 10 * number + (next_char() - '0');
  } while (isdigit(next_char(false)));

  if (negative)
    number = -number;
}

template <typename T, typename... Args>
inline void read_int(T &number, Args &...args) {
  read_int(number);
  read_int(args...);
}

void _flush_output() {
  fwrite(output_buffer, sizeof(char), output_pos, stdout);
  output_pos = 0;
}

inline void write_char(char c) {
  if (output_pos == BUFFER_SIZE)
    _flush_output();

  output_buffer[output_pos++] = c;
}

template <typename T> inline void write_int(T number, char after = '\\0') {
  if (number < 0) {
    write_char('-');
    number = -number;
  }
  int length = 0;
  while (number >= 10) {
    uint8_t lookup_value = lookup[number % 100];
    number /= 100;
    number_buffer[length++] = (lookup_value & 15) + '0';
    number_buffer[length++] = (lookup_value >> 4) + '0';
  }
  if (number != 0 || length == 0)
    write_char(number + '0');
  for (int i = length - 1; i >= 0; i--)
    write_char(number_buffer[i]);
  if (after)
    write_char(after);
}
void IOinit() {
  // Make sure _flush_output() is called at the end of the program.
  bool exit_success = atexit(_flush_output) == 0;
  assert(exit_success);
  for (int i = 0; i < 100; i++)
    lookup[i] = (i / 10 << 4) + i % 10;
}
} // namespace IO

using namespace IO;

/* ---------------- typedefs ----------------*/
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector<ll> vll;

/* ---------------- utility functions ---------------- */

int dr[] = {0, 1, -1, 0, 1, -1, 1, -1};
int dc[] = {1, 0, 0, -1, 1, -1, -1, 1};
int drr[] = {-2, -1, 0, 1, 2};
int dcc[] = {-2, -1, 0, 1, 2};
bool chk(int a, int b, int n, int m) {
  return 0 <= a && a < n && 0 <= b && b < m;
}

ll exp(ll n, ll m, ll md) {
  ll a = 1;
  while (m > 0) {
    if (m & 1)
      a = (a * n % md) % md;
    m /= 2;
    n = (n * n) % md;
  }
  return a % md;
}

ll expm(ll n, ll m) {
  ll a = 1;
  while (m > 0) {
    if (a < 0 or a >= (1e18 + n - 1) / n) {
      return -1;
    }
    if (m & 1)
      a = (a * n);
    m /= 2;
    n = (n * n);
  }
  return a;
}

void disp(vi v) {
  for (auto u : v)
    cout << u << " ";
  cout << "\\n";
}
void disp(vll v) {
  for (auto u : v)
    cout << u << " ";
  cout << endl;
}

int getSqr(int x) {
  if (x < 0)
    return -1;
  int l = sqrt(x);
  for (int i = -2; i <= 2; ++i)
    if (l + i >= 0 && (l + i) * (l + i) == x)
      return l;
  return -1;
}

const int NPRR = 1e7;
vi lp;
vector<int> prr;
void prfac(int n = NPRR) {
  assert(n <= NPRR);
  lp.assign(n + 1, 0);
  int i;
  for (i = 2; i <= n; ++i) {
    if (lp[i] == 0) {
      lp[i] = i;
      prr.push_back(i);
    }
    for (int u : prr) {
      if (i * u > n || u > lp[i])
        break;
      lp[i * u] = u;
    }
  }
}

bool check_composite_for_prime_function(ll n, ll a, ll d, int s) {
  ll x = exp(a, d, n);
  if (x == 1 || x == n - 1)
    return false;
  for (int r = 1; r < s; ++r) {
    x = x * x % n;
    x %= n;
    if (x == n - 1)
      return false;
  }
  return true;
}
bool prime(ll n) {
  if (n < 4)
    return n == 2 || n == 3;
  if (!(n & 1))
    return false;
  int s = 0;
  ll d = n - 1;
  while (!(d & 1)) {
    d >>= 1;
    s++;
  }
  for (int a : {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37}) {
    if (n == a)
      return true;
    if (check_composite_for_prime_function(n, a, d, s))
      return false;
  }
  return true;
}

ll binomialCoeff(ll n, ll k) {
  ll res = 1;

  // Since C(n, k) = C(n, n-k)
  if (k > n - k)
    k = n - k;

  // Calculate value of
  // [n * (n-1) *---* (n-k+1)] / [k * (k-1) *----* 1]
  for (ll i = 0; i < k; ++i) {
    res *= (n - i);
    res /= (i + 1);
  }

  return res;
}
/* custom hash for unordered map */
struct custom_hash {
  static uint64_t splitmix64(uint64_t x) {
    // http://xorshift.di.unimi.it/splitmix64.c
    x += 0x9e3779b97f4a7c15;
    x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
    x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
    return x ^ (x >> 31);
  }

  size_t operator()(uint64_t x) const {
    static const uint64_t FIXED_RANDOM =
        chrono::steady_clock::now().time_since_epoch().count();
    return splitmix64(x + FIXED_RANDOM);
  }
};

inline void read(int &x) { scanf("%d", &x); }

auto random_address = [] {
  char *p = new char;
  delete p;
  return uint64_t(p);
};

const uint64_t SEED = chrono::steady_clock::now().time_since_epoch().count() *
                      (random_address() | 1);
mt19937_64 rng(SEED);

/* ---------------- constants ---------------- */
const ll MAXn = 1e6 + 33, MAXlg = __lg(MAXn) + 2;
const ll MOD = 1000000007;
const ll INF = ll(1e15);

/* ---------------- gcd_extended ---------------- */
/*
 * CAREFUL: Overflow at x *= c/g out of 10**18
 * Lookout for A = 0 or B = 0
 */
void shift(ll &x, ll &y, ll cnt, ll a, ll b) {
  x += cnt * b;
  y -= cnt * a;
}
ll gcd(ll a, ll b, ll &x, ll &y) {
  if (b == 0) {
    x = 1;
    y = 0;
    return a;
  }
  ll x1, y1;
  ll d = gcd(b, a % b, x1, y1);
  x = y1;
  y = x1 - y1 * (a / b);
  return d;
}
bool give_range(ll a, ll b, ll c, ll mina, ll maxa, ll minb, ll maxb, ll &lx,
                ll &rx) {
  ll x, y;
  ll g = gcd(a, b, x, y);
  if (c % g != 0)
    return false;
  //    out2(x, y);
  x *= c / g;
  y *= c / g;
  //    out2(x, y);
  a /= g;
  b /= g;
  if (a == 0 || b == 0) {
    if (x >= mina && x <= maxa && y >= minb && y <= maxb) {
      lx = x;
      rx = x;
      return true;
    }
    return false;
  }
  ll sign_a = (a > 0 ? 1 : -1);
  ll sign_b = (b > 0 ? 1 : -1);
  ll lx1, lx2, rx1, rx2;
  {
    ll cnt = (mina - x) / b;
    shift(x, y, cnt, a, b);
    if (x < 0)
      shift(x, y, sign_a, a, b);
    if (x > maxa) {
      return false;
    }
    //        out2(x, y);

    lx1 = x;
  }
  {
    ll cnt = (maxa - x) / b;
    shift(x, y, cnt, a, b);
    //        out2(x, y);
    rx1 = x;
  }
  {
    ll cnt = -(minb - y) / a;
    shift(x, y, cnt, a, b);
    if (y < 0)
      shift(x, y, -sign_b, a, b);
    if (y > maxb) {
      return false;
    }
    //        out2(x, y);

    lx2 = x;
  }
  {
    ll cnt = -(maxb - y) / a;
    shift(x, y, cnt, a, b);
    //        out2(x, y);

    rx2 = x;
  }
  if (lx2 > rx2)
    swap(lx2, rx2);
  //    out4(lx1, lx2, rx1, rx2);

  ll lxx = max(lx1, lx2);
  ll rxx = min(rx1, rx2);
  if (lxx > rxx) {
    return false;
  }
  lx = lxx;
  rx = rxx;
  return true;
}

/* ---------------- start of code ---------------- */

/*vector<set<int> > ad;
vi par;
vi lev;
vi maxdepth;
int n;
void dfs_for_par(int s, int parent, int level) {
    par[s] = parent;
    lev[s] = level;
    for(auto u: ad[s]) {
        if(u==parent) continue;
        dfs_for_par(u, s, level+1);
    }
}
int dfsmaxdepth(int s, int e) {
    int res = 0;
    for(auto u: ad[s]) {
        if(u == e) continue;
        dfsmaxdepth(u,s);
        res = max(res, maxdepth[u]);
    }
    maxdepth[s] = ++res;
    return res;
}
vi ans;
void dfs(int s, int e) {
    vi res(n+1, 0);
    for(auto u: ad[s]) {
        if(u == e) continue;
        res[0]++;
        res[maxdepth[u]+1]--;
    }
    for(auto u: ad[e]) {
        if(u == s or u == par[e]) continue;
        res[0]++;
        res[maxdepth[u] + 1]--;
    }
    forn(i, n) res[i+1] += res[i];
    forn(i, n+1) ans[i] = max(ans[i], res[i]);
    for(auto u: ad[s]) {
        if(u == e) continue;
        dfs(u, s);
    }
}
void go2() {
    cin >> n;
    ad.assign(n, {});
    par.assign(n,0);
    ans.assign(n,0);
    lev.assign(n,0);
    maxdepth.assign(n,0);
    forn(i, n-1) {
        int r,s;in2(r,s);
        r--;s--;
        ad[r].insert(s);
        ad[s].insert(r);
    }
    if(n == 2) {
        out2(2, 2);
        return;
    }
    dfs_for_par(0,0,0);
    dfsmaxdepth(0,0);

}

void go1() {
    int n;
    string s;cin >> s;
    n = s.size();
    int i = 0;
    if(n <=3) {
        cout << s[0] << ln;
        return;
    }
    string ans;
    while(i < n/2) {
        if(n % 4 > 0 and i >= (n/4 * 4) / 2) break;
        int cnt[3] = {0};
        cnt[s[i] - 'a']++;
        cnt[s[i+1] - 'a']++;
        cnt[s[n-i-1] - 'a']++;
        cnt[s[n-i-2] - 'a']++;
        forn(j, 3) {
            if(cnt[j] > 1) {
                ans += (char)(j + 'a');
                break;
            }
        }
        i+=2;
    }

    string anss = ans;
    reverse(all(anss));
    if(n % 4 > 0) {
        ans += s[n/2];
    }
    ans += anss;
    assert(ans.size() >= n/2);
    cout << ans << ln;

}
ll md = 998244353;
void go3() {
    ll n;cin >> n;
    ll q;cin >> q;
    ll a[n];
    forn(i, n) cin >> a[i];
    if(n == 1) {
        cout << a[0] << ln;
        return;
    }
    if(n == 2) {
        cout << max(a[0], a[1]) << ln;
        return;
    }
    ll o[n], e[n];
    o[0] = a[0];
    e[0] = -1e9-7;
    o[1] = a[1];
    e[1] = a[0] - a[1];
    ll me = max(e[0], e[1]);
    ll mo = max(o[0], o[1]);
    ll prev[n];
    prev[0] = -1;
    prev[1] = -1;
    forsn(i, 2, n) {

        o[i] = max(a[i], me + a[i]);
        e[i] = mo - a[i];
        me = max(me, e[i]);
        mo = max(mo, o[i]);
    }
    cout << max(mo, me) << ln;
}
ll c(ll n, ll k) {
    if(n <= 0 or k > n) {
        return 0;
    }
    ll res = 1;
    k = min(k, n - k);
    forn(i, k) {
        res = (res * (ll)(n - i)) % md;
        res /= (ll)(i + 1);
        res %= md;
    }
    return res;
}*/
namespace SegmentTree {
int n;
pii t[4 * MAXn];
int mod[4 * MAXn] = {0};
vi a;

void pull(int v) {
  t[v] = {max(t[2 * v + 1].F, t[2 * v + 2].F),
          min(t[2 * v + 1].S, t[2 * v + 2].S)};
}

void apply(int v, int val) {
  t[v] = {max(t[v].F, val), val};
  mod[v] = val;
}

void push(int v) {
  if (mod[v] != 0) {
    apply(2 * v + 1, mod[v]);
    apply(2 * v + 2, mod[v]);
    mod[v] = 0;
  }
}

void build(int v, int l, int r) {
  if (l + 1 == r) {
    t[v] = {a[l], a[l]};
  } else {
    int m = (r + l) >> 1;
    build(2 * v + 1, l, m);
    build(2 * v + 2, m, r);
    pull(v);
  }
  //        out4(v, t[v], l, r);
}

void modify_max(int v, int l, int r, int ql, int qr, int val) {
  if (r <= ql || qr <= l) {
    return;
  } else if (ql <= l && r <= qr) {
    apply(v, val);
  } else {
    push(v);
    int m = (r + l) >> 1;
    modify_max(2 * v + 1, l, m, ql, qr, val);
    modify_max(2 * v + 2, m, r, ql, qr, val);
    pull(v);
  }
}
void modify_max(int l, int r, int val) { modify_max(0, 0, n, l, r, val); }
void modify_max(int pos, int val) { modify_max(0, 0, n, pos, pos + 1, val); }

void init(int n_) {
  n = n_;
  build(0, 0, n);
}
void init(const vi &b) {
  n = (int)b.size();
  a.clear();
  for (const auto &u : b)
    a.PB(u);
  build(0, 0, n);
}

int getval_max(int v, int ql, int qr, int l, int r) {
  if (r <= ql || qr <= l) {
    return 0;
  } else if (ql <= l && r <= qr) {
    return t[v].F;
  }
  push(v);
  int res = 0;
  int mid = (l + r) >> 1;
  res = max(res, getval_max(2 * v + 1, ql, qr, l, mid));
  res = max(res, getval_max(2 * v + 2, ql, qr, mid, r));
  pull(v);
  return res;
}
// ql, qr analogous to modify_max(). 0-indexed.
ll getval_max(int ql, int qr) { return getval_max(0, ql, qr, 0, n); }
} // namespace SegmentTree

vi b(1000033, 0);
vi anss;
void go4() {
  int n, k;
  in2(n, k);
  vi a(n);
  anss.assign(n, 0);
  forn(i, n) cin >> a[i];
  SegmentTree::init(b);
  anss[0] = 1;
  int j = 3e5 + 1 + a[0];
  SegmentTree::modify_max(j, j + 1, 1);
  //    forn(i, 10) {
  //        cout << SegmentTree::getval_max(3e5+1+i, 3e5+1+i+1) << " ";
  //    }cout << ln;
  int ans = SegmentTree::getval_max(0, 1e6 + 30);
  forsn(i, 1, n) {
    int j = 3e5 + 1 + a[i];
    int p = SegmentTree::getval_max(j - k, j + k + 1);
    // cout << p << " ";
    p++;
    SegmentTree::modify_max(j, j + 1, p);
    anss[i] = p;
    ans = max(ans, p);
    forn(i, 12) {
      cerr << SegmentTree::getval_max(3e5 + 1 + i, 3e5 + 1 + i + 1) << " ";
    }
    cerr << ln;
  }
  //    cout << ln;
  //    forn(i, 10) {
  //        cout << SegmentTree::getval_max(3e5+1+i, 3e5+1+i+1) << " ";
  //    }cout << ln;
  // disp(anss);
  cout << ans << ln;
}

int main() {
  fio;
  fflush(stdout);
  cout << fixed << setprecision(0);
  cerr << fixed << setprecision(10);

  // freopen("input.txt","r",stdin);freopen("output.txt","w",stdout);

  ll tt = 1;

  /*

      cin >> tt;
      ll t = tt;

      //*/
  // forn(i, 100) cout << fac[i] << " ";

  auto start = std::chrono::high_resolution_clock::now();

  while (tt--) {
    // cout << "Case #" << t - tt << ": ";
    go4();
  }
  auto stop = std::chrono::high_resolution_clock::now();
  auto duration =
      std::chrono::duration_cast<std::chrono::nanoseconds>(stop - start);
  // cerr << "Time taken : " << ((long double)duration.count())/((long double)
  // 1e9) <<"s "<< endl;
  return 0;
}
/* ---------------- end of code ---------------- */

#pragma GCC target("sse4.2")
#include <bits/stdc++.h>

using namespace std;

#define F first
#define S second
#define PB push_back
#define ln "\\n"
#define forn(i, e) for (ll i = 0; i < e; i++)
#define forsn(i, s, e) for (ll i = s; i < e; i++)
#define rforn(i, e) for (ll i = e; i >= 0; i--)
#define rforsn(i, e, s) for (ll i = e; i >= s; i--)
#define vasort(v) sort(v.begin(), v.end());
#define vdsort(v) sort(v.begin(), v.end(), greater<ll>());
#define fio                                                                    \\
  ios_base::sync_with_stdio(false);                                            \\
  cin.tie(NULL);                                                               \\
  cout.tie(NULL)
#define mem(a, b) memset(a, b, sizeof(a))
#define sz(x) ((int)size(x))
#define EB emplace_back
#define flush fflush(stdout)
#define out1(x1) cout << x1 << ln
#define out2(x1, x2) cout << x1 << " " << x2 << endl
#define out3(x1, x2, x3) cout << x1 << " " << x2 << " " << x3 << endl
#define out4(x1, x2, x3, x4)                                                   \\
  cout << x1 << " " << x2 << " " << x3 << " " << x4 << ln
#define all(d) d.begin(), d.end()
#define unordered_set(T) unordered_set<T, custom_hash>
#define unordered_map(T1, T2) unordered_map<T1, T2, custom_hash>

#define in1(x1) cin >> x1
#define in2(x1, x2) cin >> x1 >> x2
#define in3(x1, x2, x3) cin >> x1 >> x2 >> x3
#define in4(x1, x2, x3, x4) cin >> x1 >> x2 >> x3 >> x4

#define arrin(a, n) forn(i, n) cin >> a[i];
#define arrout(a, n)                                                           \\
  forn(i, n) { cout << a[i] << " "; }                                          \\
  cout << ln;

/* ---------------- IO ----------------*/

namespace IO {
const int BUFFER_SIZE = 1 << 15;
char input_buffer[BUFFER_SIZE];
int input_pos = 0, input_len = 0;
char output_buffer[BUFFER_SIZE];
int output_pos = 0;
char number_buffer[100];
uint8_t lookup[100];
void _update_input_buffer() {
  input_len = fread(input_buffer, sizeof(char), BUFFER_SIZE, stdin);
  input_pos = 0;
  if (input_len == 0)
    input_buffer[0] = EOF;
}
inline char next_char(bool advance = true) {
  if (input_pos >= input_len)
    _update_input_buffer();

  return input_buffer[advance ? input_pos++ : input_pos];
}

template <typename T> inline void read_int(T &number) {
  bool negative = false;
  number = 0;

  while (!isdigit(next_char(false)))
    if (next_char() == '-')
      negative = true;

  do {
    number = 10 * number + (next_char() - '0');
  } while (isdigit(next_char(false)));

  if (negative)
    number = -number;
}

template <typename T, typename... Args>
inline void read_int(T &number, Args &...args) {
  read_int(number);
  read_int(args...);
}

void _flush_output() {
  fwrite(output_buffer, sizeof(char), output_pos, stdout);
  output_pos = 0;
}

inline void write_char(char c) {
  if (output_pos == BUFFER_SIZE)
    _flush_output();

  output_buffer[output_pos++] = c;
}

template <typename T> inline void write_int(T number, char after = '\\0') {
  if (number < 0) {
    write_char('-');
    number = -number;
  }
  int length = 0;
  while (number >= 10) {
    uint8_t lookup_value = lookup[number % 100];
    number /= 100;
    number_buffer[length++] = (lookup_value & 15) + '0';
    number_buffer[length++] = (lookup_value >> 4) + '0';
  }
  if (number != 0 || length == 0)
    write_char(number + '0');
  for (int i = length - 1; i >= 0; i--)
    write_char(number_buffer[i]);
  if (after)
    write_char(after);
}
void IOinit() {
  // Make sure _flush_output() is called at the end of the program.
  bool exit_success = atexit(_flush_output) == 0;
  assert(exit_success);
  for (int i = 0; i < 100; i++)
    lookup[i] = (i / 10 << 4) + i % 10;
}
} // namespace IO

using namespace IO;

/* ---------------- typedefs ----------------*/
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector<ll> vll;

/* ---------------- utility functions ---------------- */

int dr[] = {0, 1, -1, 0, 1, -1, 1, -1};
int dc[] = {1, 0, 0, -1, 1, -1, -1, 1};
int drr[] = {-2, -1, 0, 1, 2};
int dcc[] = {-2, -1, 0, 1, 2};
bool chk(int a, int b, int n, int m) {
  return 0 <= a && a < n && 0 <= b && b < m;
}

ll exp(ll n, ll m, ll md) {
  ll a = 1;
  while (m > 0) {
    if (m & 1)
      a = (a * n % md) % md;
    m /= 2;
    n = (n * n) % md;
  }
  return a % md;
}

ll expm(ll n, ll m) {
  ll a = 1;
  while (m > 0) {
    if (a < 0 or a >= (1e18 + n - 1) / n) {
      return -1;
    }
    if (m & 1)
      a = (a * n);
    m /= 2;
    n = (n * n);
  }
  return a;
}

void disp(vi v) {
  for (auto u : v)
    cout << u << " ";
  cout << "\\n";
}
void disp(vll v) {
  for (auto u : v)
    cout << u << " ";
  cout << endl;
}

int getSqr(int x) {
  if (x < 0)
    return -1;
  int l = sqrt(x);
  for (int i = -2; i <= 2; ++i)
    if (l + i >= 0 && (l + i) * (l + i) == x)
      return l;
  return -1;
}

const int NPRR = 1e7;
vi lp;
vector<int> prr;
void prfac(int n = NPRR) {
  assert(n <= NPRR);
  lp.assign(n + 1, 0);
  int i;
  for (i = 2; i <= n; ++i) {
    if (lp[i] == 0) {
      lp[i] = i;
      prr.push_back(i);
    }
    for (int u : prr) {
      if (i * u > n || u > lp[i])
        break;
      lp[i * u] = u;
    }
  }
}

bool check_composite_for_prime_function(ll n, ll a, ll d, int s) {
  ll x = exp(a, d, n);
  if (x == 1 || x == n - 1)
    return false;
  for (int r = 1; r < s; ++r) {
    x = x * x % n;
    x %= n;
    if (x == n - 1)
      return false;
  }
  return true;
}
bool prime(ll n) {
  if (n < 4)
    return n == 2 || n == 3;
  if (!(n & 1))
    return false;
  int s = 0;
  ll d = n - 1;
  while (!(d & 1)) {
    d >>= 1;
    s++;
  }
  for (int a : {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37}) {
    if (n == a)
      return true;
    if (check_composite_for_prime_function(n, a, d, s))
      return false;
  }
  return true;
}

ll binomialCoeff(ll n, ll k) {
  ll res = 1;

  // Since C(n, k) = C(n, n-k)
  if (k > n - k)
    k = n - k;

  // Calculate value of
  // [n * (n-1) *---* (n-k+1)] / [k * (k-1) *----* 1]
  for (ll i = 0; i < k; ++i) {
    res *= (n - i);
    res /= (i + 1);
  }

  return res;
}
/* custom hash for unordered map */
struct custom_hash {
  static uint64_t splitmix64(uint64_t x) {
    // http://xorshift.di.unimi.it/splitmix64.c
    x += 0x9e3779b97f4a7c15;
    x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
    x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
    return x ^ (x >> 31);
  }

  size_t operator()(uint64_t x) const {
    static const uint64_t FIXED_RANDOM =
        chrono::steady_clock::now().time_since_epoch().count();
    return splitmix64(x + FIXED_RANDOM);
  }
};

inline void read(int &x) { scanf("%d", &x); }

auto random_address = [] {
  char *p = new char;
  delete p;
  return uint64_t(p);
};

const uint64_t SEED = chrono::steady_clock::now().time_since_epoch().count() *
                      (random_address() | 1);
mt19937_64 rng(SEED);

/* ---------------- constants ---------------- */
const ll MAXn = 1e6 + 33, MAXlg = __lg(MAXn) + 2;
const ll MOD = 1000000007;
const ll INF = ll(1e15);

/* ---------------- gcd_extended ---------------- */
/*
 * CAREFUL: Overflow at x *= c/g out of 10**18
 * Lookout for A = 0 or B = 0
 */
void shift(ll &x, ll &y, ll cnt, ll a, ll b) {
  x += cnt * b;
  y -= cnt * a;
}
ll gcd(ll a, ll b, ll &x, ll &y) {
  if (b == 0) {
    x = 1;
    y = 0;
    return a;
  }
  ll x1, y1;
  ll d = gcd(b, a % b, x1, y1);
  x = y1;
  y = x1 - y1 * (a / b);
  return d;
}
bool give_range(ll a, ll b, ll c, ll mina, ll maxa, ll minb, ll maxb, ll &lx,
                ll &rx) {
  ll x, y;
  ll g = gcd(a, b, x, y);
  if (c % g != 0)
    return false;
  //    out2(x, y);
  x *= c / g;
  y *= c / g;
  //    out2(x, y);
  a /= g;
  b /= g;
  if (a == 0 || b == 0) {
    if (x >= mina && x <= maxa && y >= minb && y <= maxb) {
      lx = x;
      rx = x;
      return true;
    }
    return false;
  }
  ll sign_a = (a > 0 ? 1 : -1);
  ll sign_b = (b > 0 ? 1 : -1);
  ll lx1, lx2, rx1, rx2;
  {
    ll cnt = (mina - x) / b;
    shift(x, y, cnt, a, b);
    if (x < 0)
      shift(x, y, sign_a, a, b);
    if (x > maxa) {
      return false;
    }
    //        out2(x, y);

    lx1 = x;
  }
  {
    ll cnt = (maxa - x) / b;
    shift(x, y, cnt, a, b);
    //        out2(x, y);
    rx1 = x;
  }
  {
    ll cnt = -(minb - y) / a;
    shift(x, y, cnt, a, b);
    if (y < 0)
      shift(x, y, -sign_b, a, b);
    if (y > maxb) {
      return false;
    }
    //        out2(x, y);

    lx2 = x;
  }
  {
    ll cnt = -(maxb - y) / a;
    shift(x, y, cnt, a, b);
    //        out2(x, y);

    rx2 = x;
  }
  if (lx2 > rx2)
    swap(lx2, rx2);
  //    out4(lx1, lx2, rx1, rx2);

  ll lxx = max(lx1, lx2);
  ll rxx = min(rx1, rx2);
  if (lxx > rxx) {
    return false;
  }
  lx = lxx;
  rx = rxx;
  return true;
}

/* ---------------- start of code ---------------- */

/*vector<set<int> > ad;
vi par;
vi lev;
vi maxdepth;
int n;
void dfs_for_par(int s, int parent, int level) {
    par[s] = parent;
    lev[s] = level;
    for(auto u: ad[s]) {
        if(u==parent) continue;
        dfs_for_par(u, s, level+1);
    }
}
int dfsmaxdepth(int s, int e) {
    int res = 0;
    for(auto u: ad[s]) {
        if(u == e) continue;
        dfsmaxdepth(u,s);
        res = max(res, maxdepth[u]);
    }
    maxdepth[s] = ++res;
    return res;
}
vi ans;
void dfs(int s, int e) {
    vi res(n+1, 0);
    for(auto u: ad[s]) {
        if(u == e) continue;
        res[0]++;
        res[maxdepth[u]+1]--;
    }
    for(auto u: ad[e]) {
        if(u == s or u == par[e]) continue;
        res[0]++;
        res[maxdepth[u] + 1]--;
    }
    forn(i, n) res[i+1] += res[i];
    forn(i, n+1) ans[i] = max(ans[i], res[i]);
    for(auto u: ad[s]) {
        if(u == e) continue;
        dfs(u, s);
    }
}
void go2() {
    cin >> n;
    ad.assign(n, {});
    par.assign(n,0);
    ans.assign(n,0);
    lev.assign(n,0);
    maxdepth.assign(n,0);
    forn(i, n-1) {
        int r,s;in2(r,s);
        r--;s--;
        ad[r].insert(s);
        ad[s].insert(r);
    }
    if(n == 2) {
        out2(2, 2);
        return;
    }
    dfs_for_par(0,0,0);
    dfsmaxdepth(0,0);

}

void go1() {
    int n;
    string s;cin >> s;
    n = s.size();
    int i = 0;
    if(n <=3) {
        cout << s[0] << ln;
        return;
    }
    string ans;
    while(i < n/2) {
        if(n % 4 > 0 and i >= (n/4 * 4) / 2) break;
        int cnt[3] = {0};
        cnt[s[i] - 'a']++;
        cnt[s[i+1] - 'a']++;
        cnt[s[n-i-1] - 'a']++;
        cnt[s[n-i-2] - 'a']++;
        forn(j, 3) {
            if(cnt[j] > 1) {
                ans += (char)(j + 'a');
                break;
            }
        }
        i+=2;
    }

    string anss = ans;
    reverse(all(anss));
    if(n % 4 > 0) {
        ans += s[n/2];
    }
    ans += anss;
    assert(ans.size() >= n/2);
    cout << ans << ln;

}
ll md = 998244353;
void go3() {
    ll n;cin >> n;
    ll q;cin >> q;
    ll a[n];
    forn(i, n) cin >> a[i];
    if(n == 1) {
        cout << a[0] << ln;
        return;
    }
    if(n == 2) {
        cout << max(a[0], a[1]) << ln;
        return;
    }
    ll o[n], e[n];
    o[0] = a[0];
    e[0] = -1e9-7;
    o[1] = a[1];
    e[1] = a[0] - a[1];
    ll me = max(e[0], e[1]);
    ll mo = max(o[0], o[1]);
    ll prev[n];
    prev[0] = -1;
    prev[1] = -1;
    forsn(i, 2, n) {

        o[i] = max(a[i], me + a[i]);
        e[i] = mo - a[i];
        me = max(me, e[i]);
        mo = max(mo, o[i]);
    }
    cout << max(mo, me) << ln;
}
ll c(ll n, ll k) {
    if(n <= 0 or k > n) {
        return 0;
    }
    ll res = 1;
    k = min(k, n - k);
    forn(i, k) {
        res = (res * (ll)(n - i)) % md;
        res /= (ll)(i + 1);
        res %= md;
    }
    return res;
}*/
namespace SegmentTree {
int n;
pii t[4 * MAXn];
int mod[4 * MAXn] = {0};
vi a;

void pull(int v) {
  t[v] = {max(t[2 * v + 1].F, t[2 * v + 2].F),
          min(t[2 * v + 1].S, t[2 * v + 2].S)};
}

void apply(int v, int val) {
  t[v] = {max(t[v].F, val), val};
  mod[v] = val;
}

void push(int v) {
  if (mod[v] != 0) {
    apply(2 * v + 1, mod[v]);
    apply(2 * v + 2, mod[v]);
    mod[v] = 0;
  }
}

void build(int v, int l, int r) {
  if (l + 1 == r) {
    t[v] = {a[l], a[l]};
  } else {
    int m = (r + l) >> 1;
    build(2 * v + 1, l, m);
    build(2 * v + 2, m, r);
    pull(v);
  }
  //        out4(v, t[v], l, r);
}

void modify_max(int v, int l, int r, int ql, int qr, int val) {
  if (r <= ql || qr <= l) {
    return;
  } else if (ql <= l && r <= qr) {
    apply(v, val);
  } else {
    push(v);
    int m = (r + l) >> 1;
    modify_max(2 * v + 1, l, m, ql, qr, val);
    modify_max(2 * v + 2, m, r, ql, qr, val);
    pull(v);
  }
}
void modify_max(int l, int r, int val) { modify_max(0, 0, n, l, r, val); }
void modify_max(int pos, int val) { modify_max(0, 0, n, pos, pos + 1, val); }

void init(int n_) {
  n = n_;
  build(0, 0, n);
}
void init(const vi &b) {
  n = (int)b.size();
  a.clear();
  for (const auto &u : b)
    a.PB(u);
  build(0, 0, n);
}

int getval_max(int v, int ql, int qr, int l, int r) {
  if (r <= ql || qr <= l) {
    return 0;
  } else if (ql <= l && r <= qr) {
    return t[v].F;
  }
  push(v);
  int res = 0;
  int mid = (l + r) >> 1;
  res = max(res, getval_max(2 * v + 1, ql, qr, l, mid));
  res = max(res, getval_max(2 * v + 2, ql, qr, mid, r));
  pull(v);
  return res;
}
// ql, qr analogous to modify_max(). 0-indexed.
ll getval_max(int ql, int qr) { return getval_max(0, ql, qr, 0, n); }
} // namespace SegmentTree

vi b(1000033, 0);
vi anss;
void go4() {
  int n, k;
  in2(n, k);
  vi a(n);
  anss.assign(n, 0);
  forn(i, n) cin >> a[i];
  SegmentTree::init(b);
  anss[0] = 1;
  int j = 3e5 + 1 + a[0];
  SegmentTree::modify_max(j, j + 1, 1);
  //    forn(i, 10) {
  //        cout << SegmentTree::getval_max(3e5+1+i, 3e5+1+i+1) << " ";
  //    }cout << ln;
  int ans = SegmentTree::getval_max(0, 1e6 + 30);
  forsn(i, 1, n) {
    int j = 3e5 + 1 + a[i];
    int p = SegmentTree::getval_max(j - k, j + k + 1);
    // cout << p << " ";
    p++;
    SegmentTree::modify_max(j, j + 1, p);
    anss[i] = p;
    ans = max(ans, p);
    //        forn(i, 12) {
    //            cerr << SegmentTree::getval_max(3e5+1+i, 3e5+1+i+1) << " ";
    //        }cerr << ln;
  }
  //    cout << ln;
  //    forn(i, 10) {
  //        cout << SegmentTree::getval_max(3e5+1+i, 3e5+1+i+1) << " ";
  //    }cout << ln;
  // disp(anss);
  cout << ans << ln;
}

int main() {
  fio;
  fflush(stdout);
  cout << fixed << setprecision(0);
  cerr << fixed << setprecision(10);

  // freopen("input.txt","r",stdin);freopen("output.txt","w",stdout);

  ll tt = 1;

  /*

      cin >> tt;
      ll t = tt;

      //*/
  // forn(i, 100) cout << fac[i] << " ";

  auto start = std::chrono::high_resolution_clock::now();

  while (tt--) {
    // cout << "Case #" << t - tt << ": ";
    go4();
  }
  auto stop = std::chrono::high_resolution_clock::now();
  auto duration =
      std::chrono::duration_cast<std::chrono::nanoseconds>(stop - start);
  // cerr << "Time taken : " << ((long double)duration.count())/((long double)
  // 1e9) <<"s "<< endl;
  return 0;
}
/* ---------------- end of code ---------------- */


#pragma GCC optimize(2)
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
#define lowbit(n) n & (-n)
#define ls x << 1
#define rs x << 1 | 1
#define clc(a, b) memset(a, b, sizeof(a))
#define Buff ios::sync_with_stdio(false)
#define rush()                                                                 \\
  int Case = 0;                                                                \\
  int T;                                                                       \\
  scanf("%d", &T);                                                             \\
  while (T--)
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define per(i, a, b) for (int i = a; i >= b; i--)
#define reps(i, a, b) for (int i = a; b; i++)
#define read(a) scanf("%d", &a)
#define readd(a) scanf("%lf", &a)
#define readl(a) scanf("%lld", &a)
#define readc(a) scanf("%c", &a)
#define reads(a) scanf("%s", a)
#define sqr(x) x *x
#define pb push_back
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
const int mod = 1e9 + 7;
const double eps = 1e-6;
const int N = 3e5 + 7;
int b[N];
struct BIT // binary index tree
{
  int t[N], n;
  int a[N];
  void init(int n_) {
    n = n_;
    for (int i = 1; i <= n; i++)
      t[i] = a[i] = 0;
  }
  int query(int l, int r) {
    int res = a[r];
    while (r > l) // t[i]维护 [i-lowbit(i)+1,i]的最值
    {
      for (--r; r - lowbit(r) >= l;
           r -= lowbit(r)) // r-lowbit(r)+1>=l return max t[r],query(l,r-low(r))
        res = max(res, t[r]); // r-lowbit(r)+1<l return max a[r],query(l,r-1)
      res = max(res, a[r]);
    }
    return res;
  }
  void modify(int x, int v) {
    a[x] = v;
    while (x <= n) {
      t[x] = a[x];
      for (int i = 1, j = lowbit(x); i < j; i <<= 1) // y+( lowbit(y)=2^i) =x
        t[x] = max(
            t[x],
            t[x -
              i]); // 对pos=x的修改需要考虑其维护的(x-lowbit(x),x]区间里的数对该区间最值贡献
      x += lowbit(x); // 转移至包含该区间的下一个位置
    }
  }
};
BIT tree;
int main() {
  Buff;
  int n, k, maxv = 1, res = 0;
  cin >> n >> k;
  rep(i, 1, n) {
    cin >> b[i];
    b[i]++;
    maxv = max(maxv, b[i]);
  }
  tree.init(maxv);
  rep(i, 1, n) {
    int l = max(1, b[i] - k);
    int r = min(maxv, b[i] + k);
    int t = tree.query(l, r);
    res = max(res, t + 1);
    tree.modify(b[i], t + 1);
  }
  cout << res << endl;
  return 0;
}

#pragma GCC optimize(2)
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
// #define lowbit(n) n & (-n)
#define ls x << 1
#define rs x << 1 | 1
#define clc(a, b) memset(a, b, sizeof(a))
#define Buff ios::sync_with_stdio(false)
#define rush()                                                                 \\
  int Case = 0;                                                                \\
  int T;                                                                       \\
  scanf("%d", &T);                                                             \\
  while (T--)
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define per(i, a, b) for (int i = a; i >= b; i--)
#define reps(i, a, b) for (int i = a; b; i++)
#define read(a) scanf("%d", &a)
#define readd(a) scanf("%lf", &a)
#define readl(a) scanf("%lld", &a)
#define readc(a) scanf("%c", &a)
#define reads(a) scanf("%s", a)
#define sqr(x) x *x
#define pb push_back
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
const int mod = 1e9 + 7;
const double eps = 1e-6;
const int N = 3e5 + 7;
int b[N];
struct BIT // binary index tree
{
  int t[N], n;
  int a[N];
#define lowbit(x) (x & (-x))
  void init(int n_) {
    n = n_;
    for (int i = 1; i <= n; i++)
      t[i] = a[i] = 0;
  }
  int query(int l, int r) {
    int res = a[r];
    while (r > l) // t[i]维护 [i-lowbit(i)+1,i]的最值
    {
      for (--r; r - lowbit(r) >= l;
           r -= lowbit(r)) // r-lowbit(r)+1>=l return max t[r],query(l,r-low(r))
        res = max(res, t[r]); // r-lowbit(r)+1<l return max a[r],query(l,r-1)
      res = max(res, a[r]);
    }
    return res;
  }
  void modify(int x, int v) {
    a[x] = v;
    while (x <= n) {
      t[x] = a[x];
      for (int i = 1, j = lowbit(x); i < j; i <<= 1) // y+( lowbit(y)=2^i) =x
        t[x] = max(
            t[x],
            t[x -
              i]); // 对pos=x的修改需要考虑其维护的(x-lowbit(x),x]区间里的数对该区间最值贡献
      x += lowbit(x); // 转移至包含该区间的下一个位置
    }
  }
};
BIT tree;
int main() {
  Buff;
  int n, k, maxv = 1, res = 0;
  cin >> n >> k;
  rep(i, 1, n) {
    cin >> b[i];
    b[i]++;
    maxv = max(maxv, b[i]);
  }
  tree.init(maxv);
  rep(i, 1, n) {
    int l = max(1, b[i] - k);
    int r = min(maxv, b[i] + k);
    int t = tree.query(l, r);
    res = max(res, t + 1);
    tree.modify(b[i], t + 1);
  }
  cout << res << endl;
  return 0;
}


#include <iostream>
using namespace std;
const int maxn = 3e6 + 7;
struct node {
  int l, r, s;
} pre[maxn];
int n, k, mx, a[maxn];
void build(int k, int l, int r);
void update(int k, int l, int r);
int query(int k, int l, int r);
int main() {
  scanf("%d %d", &n, &k);
  for (int i = 1; i <= n; i++) {
    scanf("%d", &a[i]);
    mx = max(mx, a[i]);
  }
  build(1, 1, mx);
  int now = 0, ans = 0;
  for (int i = 1; i <= n; i++) {
    now = query(1, max(0, a[i] - k), min(mx, a[i] + k)) + 1;
    ans = max(ans, now);
    update(1, now, now);
  }
  printf("%d\\n", ans);
}

void build(int k, int l, int r) {
  pre[k].l = l, pre[k].r = r, pre[k].s = 0;
  if (l >= r)
    return;
  build(k * 2, l, (l + r) / 2);
  build(k * 2 + 1, (l + r) / 2 + 1, r);
}

void update(int k, int l, int r) {
  if (l <= pre[k].l && pre[k].r <= r) {
    pre[k].s = l;
    return;
  }
  int mid = (pre[k].l + pre[k].r) / 2;
  if (l <= mid)
    update(k * 2, l, r);
  if (mid + 1 <= r)
    update(k * 2 + 1, l, r);
  pre[k].s = max(pre[k * 2].s, pre[k * 2 + 1].s);
}

int query(int k, int l, int r) {
  if (pre[k].l <= l && pre[k].r <= r) {
    return pre[k].s;
  }
  int mid = (pre[k].l + pre[k].r) / 2;
  int ans1 = 0, ans2 = 0;
  if (l <= mid)
    ans1 = query(k * 2, l, r);
  if (mid + 1 <= r)
    ans2 = query(k * 2 + 1, l, r);
  return max(ans1, ans2);
}

#include <iostream>
using namespace std;
const int maxn = 3e6 + 7;
struct node {
  int l, r, s;
} pre[maxn];
int n, k, mx, a[maxn];
void build(int k, int l, int r);
void update(int v, int k, int l, int r);
int query(int k, int l, int r);
int main() {
  scanf("%d %d", &n, &k);
  for (int i = 1; i <= n; i++) {
    scanf("%d", &a[i]);
    mx = max(mx, a[i]);
  }
  build(1, 0, mx);
  int now = 0, ans = 0;
  for (int i = 1; i <= n; i++) {
    now = query(1, max(0, a[i] - k), min(mx, a[i] + k)) + 1;
    ans = max(ans, now);
    update(now, 1, a[i], a[i]);
  }
  printf("%d\\n", ans);
}

void build(int k, int l, int r) {
  pre[k].l = l, pre[k].r = r, pre[k].s = 0;
  if (l >= r)
    return;
  build(k * 2, l, (l + r) / 2);
  build(k * 2 + 1, (l + r) / 2 + 1, r);
}

void update(int v, int k, int l, int r) {
  if (l <= pre[k].l && pre[k].r <= r) {
    pre[k].s = v;
    return;
  }
  int mid = (pre[k].l + pre[k].r) / 2;
  if (l <= mid)
    update(v, k * 2, l, r);
  else
    update(v, k * 2 + 1, l, r);
  pre[k].s = max(pre[k * 2].s, pre[k * 2 + 1].s);
}

int query(int k, int l, int r) {
  if (l <= pre[k].l && pre[k].r <= r) {
    return pre[k].s;
  }
  int mid = (pre[k].l + pre[k].r) / 2;
  int ans1 = 0, ans2 = 0;
  if (l <= mid)
    ans1 = query(k * 2, l, r);
  if (mid + 1 <= r)
    ans2 = query(k * 2 + 1, l, r);
  return max(ans1, ans2);
}


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

// 入力
template <typename T> istream &operator>>(istream &is, vector<T> &a) {
  for (size_t i = 0; i < a.size(); i++)
    is >> a[i];
  return is;
}
template <typename T, typename U>
istream &operator>>(istream &is, pair<T, U> &p) {
  is >> p.first >> p.second;
  return is;
}

// 出力
template <typename T> ostream &operator<<(ostream &os, const vector<T> &a) {
  for (int i = 0; i < a.size(); i++) {
    os << a[i] << ((i + 1 != a.size()) ? " " : "");
  }
  return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  os << p.first << " " << p.second;
  return os;
}

// 入出力高速化
struct hishimochi {
  hishimochi() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(10);
  }
};
hishimochi Hishimochi;

// 多次元配列
template <class T> vector<T> make_vec(size_t a) { return vector<T>(a); }
template <class T, class... Ts> auto make_vec(size_t a, Ts... ts) {
  return vector<decltype(make_vec<T>(ts...))>(a, make_vec<T>(ts...));
}

// 辺
struct edge {
  long long to, cost;
  edge(long long t, long long c) : to(t), cost(c) {}
};
struct edge2 {
  long long from, to, cost;
  edge2(long long f, long long t, long long c) : from(f), to(t), cost(c) {}
};

// 型名
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using pll = pair<long long, long long>;
using vl = vector<long long>;
using vvl = vector<vector<long long>>;
using vvvl = vector<vector<vector<long long>>>;
using vi = vector<int>;
using vvi = vector<vector<int>>;
using vvvi = vector<vector<vector<int>>>;
using vc = vector<char>;
using vvc = vector<vector<char>>;
using vs = vector<string>;
using vb = vector<bool>;
using vvb = vector<vector<bool>>;
using vp = vector<pair<long long, long long>>;
using Lqueue = priority_queue<long long>;
using Squeue = priority_queue<long long, vector<long long>, greater<long long>>;

// 定数
const int MOD1 = 1000000007;
const int MOD2 = 998244353;
const long double PI = 3.1415926535897932;
const long long MAXLL = 9223372036854775807;
const int MAXI = 2147483647;
const long long INF = 2305843009213693951;
const int inf = 1073741789;
const long double eps = 0.000000001;
const int dx[] = {0, 1, 0, -1, 1, -1, 1, -1};
const int dy[] = {1, 0, -1, 0, 1, 1, -1, -1};

// マクロ
#define overload3(_1, _2, _3, name, ...) name
#define rep1(n) for (int _ = 0; _ < (n); _++)
#define rep2(i, n) for (int i = 0; i < (n); i++)
#define rep3(i, s, n) for (long long i = (s); i < (n); i++)
#define rep(...) overload3(__VA_ARGS__, rep3, rep2, rep1)(__VA_ARGS__)
#define bitrep1(n) for (int _ = 0; _ < (1LL << (n)); _++)
#define bitrep2(i, n) for (int i = 0; i < (1LL << (n)); i++)
#define bitrep3(i, s, n) for (int i = (s); i < (1LL << (n)); i++)
#define bitrep(...)                                                            \\
  overload3(__VA_ARGS__, bitrep3, bitrep2, bitrep1)(__VA_ARGS__)
#define rrep0(n) for (int i = (n)-1; i >= 0; i--)
#define rrep1(i, n) for (int i = (n)-1; i >= 0; i--)
#define rrep2(i, s, n) for (long long i = (n - 1); i >= (s); i--)
#define rrep(...) overload3(__VA_ARGS__, rrep2, rrep1, rrep0)(__VA_ARGS__)
#define rbf(a, x) for (auto &a : x)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define bitcheck(bit, i) (bit) & (1LL << (i))
#define Maxe(x) *max_element((x).begin(), (x).end())
#define Mine(x) *min_element((x).begin(), (x).end())
#define Sume(x) accumulate((x).begin(), (x).end(), 0LL)
#define Size(x) ((long long)(x).size())
#define Sort(x) sort((x).begin(), (x).end())
#define rSort(x) sort((x).rbegin(), (x).rend())
#define Rev(x) reverse((x).begin(), (x).end())
#define Lin(s) getline(cin, (s))

// 省略
#define fi first
#define se second
#define mp make_pair
#define mt make_tuple
#define eb emplace_back

// 関数
void Yes(bool a) { cout << (a ? "Yes" : "No") << endl; }
void YES(bool a) { cout << (a ? "YES" : "NO") << endl; }
long long modpow(long long x, long long n, int m) {
  long long r = 1;
  while (n > 0) {
    if (n & 1)
      (r *= x) %= m;
    (x *= x) %= m;
    n >>= 1;
  }
  return r;
}
long long Gcd(long long a, long long b) { return b ? Gcd(b, a % b) : a; }
long long Lcm(long long a, long long b) { return a / Gcd(a, b) * b; }
inline long long cutup(long long a, long long b) { return (a + b - 1) / b; }
inline long long popcnt(long long a) { return __builtin_popcountll(a); }
template <class T, class U> auto max(T a, U b) { return a > b ? a : b; }
template <class T, class U> auto min(T a, U b) { return a < b ? a : b; }
template <class T, class U> inline bool chmin(T &a, U b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T, class U> inline bool chmax(T &a, U b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> void print(T a) { cout << a << "\\n"; }
template <class t> t mypow(t a, long long b) {
  if (b == 0)
    return 1;
  if (a == 0)
    return 0;
  t x = 1;
  while (b > 0) {
    if (b & 1LL)
      x *= a;
    a *= a;
    b >>= 1LL;
  }
  return x;
}

// Segtree
// O(n)
// op 二項演算
// e 単位元
template <class S, S (*op)(S, S), S (*e)()> struct segtree {
  int _n, size, log;
  vector<S> d;
  int ceil_pow2(int n) {
    int x = 0;
    while ((1U << x) < (unsigned int)(n))
      x++;
    return x;
  }
  segtree() : segtree(0) {}
  segtree(int n) : segtree(vector<S>(n, e())) {}
  segtree(const vector<S> &v) : _n(int(v.size())) {
    log = ceil_pow2(_n);
    size = 1 << log;
    d = 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);
    }
  }
  // a[p]にxを代入する
  // O(logn)
  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);
  }
  // a[p]を返す
  // O(1)
  S get(int p) {
    assert(0 <= p && p < _n);
    return d[p + size];
  }
  // op[l,r)を返す
  // O(logn)
  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);
  }
  // op[0,n)を返す
  // n=0ではe()を返す
  // O(1)
  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;
  }
  void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
};

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

ll e() { return 0LL; }

signed main() {
  ll n, k;
  cin >> n >> k;
  vl A(n);
  rep(i, n) cin >> A[i];
  ll m = Maxe(A);
  segtree<ll, op, e> S(m + 5);
  ll res = 0;
  rep(i, n) {
    ll l = max(0, A[n - 1 - i] - 1 - k);
    ll r = min(m, A[n - 1 - i] + k);
    ll p = S.prod(l, r);
    chmax(res, p + 1);
    S.set(A[n - 1 - i] - 1, p + 1);
  }
  print(res);
}

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

// 入出力高速化
struct hishimochi {
  hishimochi() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(10);
  }
};
hishimochi Hishimochi;

// 型名
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using pll = pair<long long, long long>;
using vl = vector<long long>;
using vvl = vector<vector<long long>>;
using vvvl = vector<vector<vector<long long>>>;
using vi = vector<int>;
using vvi = vector<vector<int>>;
using vvvi = vector<vector<vector<int>>>;
using vc = vector<char>;
using vvc = vector<vector<char>>;
using vs = vector<string>;
using vb = vector<bool>;
using vvb = vector<vector<bool>>;
using vp = vector<pair<long long, long long>>;
using Lqueue = priority_queue<long long>;
using Squeue = priority_queue<long long, vector<long long>, greater<long long>>;

// 定数
const int MOD1 = 1000000007;
const int MOD2 = 998244353;
const long double PI = 3.1415926535897932;
const long long MAXLL = 9223372036854775807;
const int MAXI = 2147483647;
const long long INF = 2305843009213693951;
const int inf = 1073741789;
const long double eps = 0.000000001;
const int dx[] = {0, 1, 0, -1, 1, -1, 1, -1};
const int dy[] = {1, 0, -1, 0, 1, 1, -1, -1};

// マクロ
#define overload3(_1, _2, _3, name, ...) name
#define rep1(n) for (int _ = 0; _ < (n); _++)
#define rep2(i, n) for (int i = 0; i < (n); i++)
#define rep3(i, s, n) for (long long i = (s); i < (n); i++)
#define rep(...) overload3(__VA_ARGS__, rep3, rep2, rep1)(__VA_ARGS__)
#define bitrep1(n) for (int _ = 0; _ < (1LL << (n)); _++)
#define bitrep2(i, n) for (int i = 0; i < (1LL << (n)); i++)
#define bitrep3(i, s, n) for (int i = (s); i < (1LL << (n)); i++)
#define bitrep(...)                                                            \\
  overload3(__VA_ARGS__, bitrep3, bitrep2, bitrep1)(__VA_ARGS__)
#define rrep0(n) for (int i = (n)-1; i >= 0; i--)
#define rrep1(i, n) for (int i = (n)-1; i >= 0; i--)
#define rrep2(i, s, n) for (long long i = (n - 1); i >= (s); i--)
#define rrep(...) overload3(__VA_ARGS__, rrep2, rrep1, rrep0)(__VA_ARGS__)
#define rbf(a, x) for (auto &a : x)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define bitcheck(bit, i) (bit) & (1LL << (i))
#define Maxe(x) *max_element((x).begin(), (x).end())
#define Mine(x) *min_element((x).begin(), (x).end())
#define Sume(x) accumulate((x).begin(), (x).end(), 0LL)
#define Size(x) ((long long)(x).size())
#define Sort(x) sort((x).begin(), (x).end())
#define rSort(x) sort((x).rbegin(), (x).rend())
#define Rev(x) reverse((x).begin(), (x).end())
#define Lin(s) getline(cin, (s))

// 省略
#define fi first
#define se second
#define mp make_pair
#define mt make_tuple
#define eb emplace_back

// 関数
void Yes(bool a) { cout << (a ? "Yes" : "No") << endl; }
void YES(bool a) { cout << (a ? "YES" : "NO") << endl; }
long long modpow(long long x, long long n, int m) {
  long long r = 1;
  while (n > 0) {
    if (n & 1)
      (r *= x) %= m;
    (x *= x) %= m;
    n >>= 1;
  }
  return r;
}
long long Gcd(long long a, long long b) { return b ? Gcd(b, a % b) : a; }
long long Lcm(long long a, long long b) { return a / Gcd(a, b) * b; }
inline long long cutup(long long a, long long b) { return (a + b - 1) / b; }
inline long long popcnt(long long a) { return __builtin_popcountll(a); }
template <class T, class U> inline bool chmin(T &a, U b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T, class U> inline bool chmax(T &a, U b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> void print(T a) { cout << a << "\\n"; }
template <class t> t mypow(t a, long long b) {
  if (b == 0)
    return 1;
  if (a == 0)
    return 0;
  t x = 1;
  while (b > 0) {
    if (b & 1LL)
      x *= a;
    a *= a;
    b >>= 1LL;
  }
  return x;
}

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

ll e() { return 0LL; }

signed main() {
  ll n, k;
  cin >> n >> k;
  vl A(n);
  rep(i, n) cin >> A[i];
  ll m = Maxe(A);
  segtree<ll, op, e> S(m + 5);
  ll res = 0;
  rep(i, n) {
    ll l = max(0LL, A[n - 1 - i] - k);
    ll r = min(m + 2, A[n - 1 - i] + k + 1);
    ll p = S.prod(l, r);
    chmax(res, p + 1);
    S.set(A[n - 1 - i], p + 1);
  }
  print(res);
}


#include <bits/stdc++.h>

using namespace std;

vector<int> arr, st;
int query(int node, int l, int r, int ll, int rl) {

  if (l <= ll && r >= rl)
    return st[node];
  if (r < ll || l > rl)
    return 0;
  int mid = ll + (rl - ll) / 2;
  int left = query(2 * node + 1, l, r, ll, mid);
  int right = query(2 * node + 2, l, r, mid + 1, rl);
  return max(left, right);
}
int update(int node, int i, int v, int ll, int rl) {
  if (i < ll || i > rl)
    return st[node];
  if (ll == rl) {
    st[node] = v;
    return st[node];
  }
  int mid = ll + (rl - ll) / 2;
  if (ll <= i && i <= mid)
    int left = update(2 * node + 1, i, v, ll, mid);
  else
    int right = update(2 * node + 2, i, v, mid + 1, rl);
  st[node] = max(st[2 * node + 1], st[2 * node + 2]);
  return st[node];
}

int main() {
  int n, k;
  cin >> n >> k;
  arr.resize(n);
  int size = 1;
  while (size < 3e5)
    size *= 2;
  st.assign(2 * size, 0);
  for (int i = 0; i < n; i++) {
    cin >> arr[i];
    int l = arr[i] - k;
    int r = arr[i] + k;
    int v = query(0, l, r, 0, 2 * size - 1);
    update(0, arr[i], v + 1, 0, 2 * size - 1);
  }
  // for(auto x:st)cout<<x;
  cout << query(0, 0, 2 * size - 1, 0, 2 * size - 1) << '\\n';
}

#include <bits/stdc++.h>

using namespace std;

vector<int> arr, st;
int query(int node, int l, int r, int ll, int rl) {

  if (l <= ll && r >= rl)
    return st[node];
  if (r < ll || l > rl)
    return 0;
  int mid = ll + (rl - ll) / 2;
  int left = query(2 * node + 1, l, r, ll, mid);
  int right = query(2 * node + 2, l, r, mid + 1, rl);
  return max(left, right);
}
int update(int node, int i, int v, int ll, int rl) {
  if (i < ll || i > rl)
    return st[node];
  if (ll == rl) {
    st[node] = v;
    return st[node];
  }
  int mid = ll + (rl - ll) / 2;
  if (ll <= i && i <= mid)
    int left = update(2 * node + 1, i, v, ll, mid);
  else
    int right = update(2 * node + 2, i, v, mid + 1, rl);
  st[node] = max(st[2 * node + 1], st[2 * node + 2]);
  return st[node];
}

int main() {
  int n, k;
  cin >> n >> k;
  arr.resize(n);
  int size = 3e5;
  st.assign(1e8, 0);
  for (int i = 0; i < n; i++) {
    cin >> arr[i];
    int l = arr[i] - k;
    int r = arr[i] + k;
    int v = query(0, l, r, 0, size);
    update(0, arr[i], v + 1, 0, size);
  }
  // for(auto x:st)cout<<x;
  cout << query(0, 0, size, 0, size) << '\\n';
}


#include <bits/stdc++.h>
using namespace std;
#include <iomanip>
#include <math.h>
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
const int INF = 300005;
const int mod = 1000000007;

int N, K;

struct SegmentTree {
private:
  int n;
  vector<int> node;

public:
  SegmentTree(vector<int> v) {
    int sz = v.size();
    n = 1;
    while (n < sz)
      n *= 2;
    node.resize(2 * n - 1);
    for (int i = 0; i < sz; i++)
      node[i + n - 1] = v[i];
    for (int i = n - 2; i >= 0; i--)
      node[i] = max(node[2 * i + 1], node[2 * i + 2]);
  }

  void update(int x, int val) {
    x += (n - 1);
    node[x] = val;
    while (x > 0) {
      x = (x - 1) / 2;
      node[x] = max(node[2 * x + 1], node[2 * x + 2]);
    }
  }

  int getmax(int a, int b, int k = 0, int l = 0, int r = -1) {
    if (r < 0)
      r = n;
    if (r <= a || b <= l)
      return 0;
    if (a <= l && r <= b)
      return node[k];

    int vl = getmax(a, b, 2 * k + 1, l, (l + r) / 2);
    int vr = getmax(a, b, 2 * k + 2, (l + r) / 2, r);
    return max(vl, vr);
  }
};
int main() {
  int N, K;
  cin >> N >> K;
  SegmentTree seg(vector<int>(N, 0));
  for (int i = 0; i < N; i++) {
    int a;
    cin >> a;
    int l = max(0, a - K);
    int r = min(INF, a + K + 1);
    int v = seg.getmax(l, r);
    seg.update(a, v + 1);
  }
  cout << seg.getmax(0, INF) << endl;
  return 0;
}

#include <bits/stdc++.h>
using namespace std;
#include <iomanip>
#include <math.h>
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
const int INF = 600005;
const int mod = 1000000007;

int N, K;

struct SegmentTree {
private:
  int n;
  vector<int> node;

public:
  SegmentTree(vector<int> v) {
    int sz = v.size();
    n = 1;
    while (n < sz)
      n *= 2;
    node.resize(2 * n - 1, 0);
    for (int i = 0; i < sz; i++)
      node[i + n - 1] = v[i];
    for (int i = n - 2; i >= 0; i--)
      node[i] = max(node[2 * i + 1], node[2 * i + 2]);
  }

  void update(int x, int val) {
    x += (n - 1);
    node[x] = val;
    while (x > 0) {
      x = (x - 1) / 2;
      node[x] = max(node[2 * x + 1], node[2 * x + 2]);
    }
  }

  int getmax(int a, int b, int k = 0, int l = 0, int r = -1) {
    if (r < 0)
      r = n;
    if (r <= a || b <= l)
      return 0;
    if (a <= l && r <= b)
      return node[k];

    int vl = getmax(a, b, 2 * k + 1, l, (l + r) / 2);
    int vr = getmax(a, b, 2 * k + 2, (l + r) / 2, r);
    return max(vl, vr);
  }
};
int main() {
  int N, K;
  cin >> N >> K;
  SegmentTree seg(vector<int>(INF, 0));
  for (int i = 0; i < N; i++) {
    int a;
    cin >> a;
    int l = max(0, a - K);
    int r = min(INF, a + K + 1);
    int v = seg.getmax(l, r); // cout<<l<<" "<<r<<endl;
    seg.update(a, v + 1);     // cout<<v<<endl;
  }
  cout << seg.getmax(0, INF) << endl;
  return 0;
}


#include <algorithm>
#include <cmath>
#include <cstring>
#include <iostream>
#define ll long long
using namespace std;
const ll maxn = 6e5 + 7;
ll num[maxn];
ll tree[4 * maxn] = {0};
ll query(ll ql, ll qr, ll l, ll r, ll root) {
  if (ql <= l && qr >= r) {
    return tree[root];
  }
  ll mid = (l + r) >> 1;
  ll ans = 0;
  if (ql <= mid)
    ans = max(ans, query(ql, qr, l, mid, root * 2));
  if (qr > mid)
    ans = max(ans, query(ql, qr, mid + 1, r, root * 2 + 1));
  return ans;
}
void update(ll pos, ll val, ll l, ll r, ll root) {
  if (l == r) {
    tree[root] = val;
    return;
  }
  ll mid = (l + r) >> 1;
  if (pos <= mid)
    update(pos, val, l, mid, root * 2);
  else
    update(pos, val, mid + 1, r, root * 2 + 1);
  tree[root] = max(tree[root * 2], tree[root * 2 + 1]);
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  ll n, k;
  cin >> n >> k;
  for (ll i = 1; i <= n; i++) {
    cin >> num[i];
  }
  ll ans = 0;
  for (ll i = 1; i <= n; i++) {
    ll temp = query(max(0ll, num[i] - k), num[i] + k, 0, n, 1) + 1;
    ans = max(ans, temp);
    update(num[i], temp, 0, n, 1);
  }
  cout << ans << endl;
}

#include <algorithm>
#include <iostream>
using namespace std;
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() {
  scanf("%d %d", &n, &k);
  for (int i = 1; i <= n; i++) {
    scanf("%d", &a[i]);
  }
  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;
}


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

int main(void) {
  long long N, K;
  cin >> N >> K;
  vector<long long> A(N);
  for (long long i = 0; i < N; i++) {
    cin >> A[i];
  }
  vector<long long> count(300001, 0);
  for (long long i = 0; i < N; i++) {
    long long precount = 0;
    for (long long j = A[i] - K; j <= A[i] + K; j++) {
      if (j > 0 && j <= 300000) {
        if (precount < count[j]) {
          precount = count[j];
        }
      }
    }
    count[A[i]] = precount + 1;
  }
  long long ans = 0;
  for (long long i = 1; i < 300001; i++) {
    if (ans < count[i]) {
      ans = count[i];
    }
  }
  cout << ans << endl;
}

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

const long long INF = 0;
long long n, node[100000000];
void init(long long N_) {
  n = 1;
  while (n < N_)
    n *= 2;
  for (long long i = 0; i < 2 * n - 1; i++)
    node[i] = INF;
}
void update(long long a, long long x) {
  a += n - 1;
  node[a] = x;
  while (a > 0) {
    a = (a - 1) / 2;
    node[a] = max(node[2 * a + 1], node[2 * a + 2]);
  }
}
long long query(long long a, long long b, long long k, long long l,
                long long r) {
  if (b <= l || r <= a)
    return INF;
  if (a <= l && r <= b)
    return node[k];
  long long vl = query(a, b, 2 * k + 1, l, (l + r) / 2);
  long long vr = query(a, b, 2 * k + 2, (l + r) / 2, r);
  return max(vl, vr);
}

int main(void) {
  long long N, K;
  cin >> N >> K;
  vector<long long> A(N);
  for (long long i = 0; i < N; i++) {
    cin >> A[i];
  }
  init(300001);
  for (long long i = 0; i < N; i++) {
    long long premin = max((long long)0, A[i] - K);
    long long premax = min((long long)300000, A[i] + K);
    long long num = query(premin, premax + 1, 0, 0, n);
    update(A[i], num + 1);
  }
  long long ans = query(0, n - 1, 0, 0, n);
  cout << ans << endl;
}


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

#define int long long int
#define all(x) (x).begin(), (x).end()
#define removeDuplicates(a) a.resize(unique(all(a)) - a.begin())
#define endl '\\n'

void solve() {
  int n, k;
  cin >> n >> k;
  vector<int> a(n);
  for (int i = 0; i < n; i++) {
    cin >> a[i];
  }
  vector<int> dp(n + 1, 1LL);
  int ans = 1;
  for (int i = 0; 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);
      }
    }
    ans = max(ans, dp[i]);
  }
  cout << ans << endl;
}

int32_t main() {

  // remove for interactive problems
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);

  solve();
  cerr << "Time : " << 1000 * ((double)clock()) / (double)CLOCKS_PER_SEC
       << "ms\\n";

  return 0;
}

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

#define int long long int
#define all(x) (x).begin(), (x).end()
#define removeDuplicates(a) a.resize(unique(all(a)) - a.begin())
#define endl '\\n'

class segtree {
  int sz;
  vector<int> val;
  vector<int> opt;
  vector<int> cnt;
  int NOP = 0;
  int NEU = 0;

public:
  segtree(int n) {
    sz = 1;
    while (sz < n) {
      sz = sz * 2;
    }
    val.assign(2 * sz, NEU);
    opt.assign(2 * sz, 0LL);
    cnt.assign(2 * sz, 0LL);
  }

  // void build(vector<int>&a,int n,int curr,int left,int right){
  // 	if(right-left==1){
  // 		if(left<n){
  // 			cnt[curr]=1;
  // 			val[curr]=a[left];
  // 		}
  // 		return;
  // 	}
  // 	int mid=(left+right)/2;
  // 	build(a,n,2*curr+1,left,mid);
  // 	build(a,n,2*curr+2,mid,right);
  // 	cnt[curr]=cnt[2*curr+1]+cnt[2*curr+2];
  // 	val[curr]=val[2*curr+1]+val[2*curr+2];
  // }
  // void build(vector<int>&a,int n){
  // 	build(a,n,0,0,sz);
  // }

  // void propogate(int curr,int left,int right){
  // 	if((right-left)==1){
  // 		return;
  // 	}
  // 	if(opt[curr]!=NOP){
  // 		opt[2*curr+1]+=opt[curr];
  // 		val[2*curr+1]+=opt[curr]*cnt[2*curr+1];
  // 		opt[2*curr+2]+=opt[curr];
  // 		val[2*curr+2]+=opt[curr]*cnt[2*curr+2];
  // 		opt[curr]=NOP;
  // 	}
  // }

  void updateRange(int l, int r, int value, int curr, int left, int right) {
    if (left >= r || right <= l) {
      return;
    }
    // propogate(curr,left,right);
    if (left >= l && right <= r) {
      opt[curr] += value;
      val[curr] += value * cnt[curr];
      return;
    }
    int mid = (left + right) / 2;
    updateRange(l, r, value, 2 * curr + 1, left, mid);
    updateRange(l, r, value, 2 * curr + 2, mid, right);
    val[curr] = max(val[2 * curr + 1], val[2 * curr + 2]);
  }
  void updateRange(int l, int r, int value) {
    updateRange(l, r, value, 0, 0, sz);
  }

  void updateIndex(int i, int value, int curr, int left, int right) {
    if (right - left == 1) {
      val[curr] = max(value, val[curr]);
      return;
    }
    int mid = (left + right) / 2;
    if (i < mid) {
      updateIndex(i, value, 2 * curr + 1, left, mid);
    } else {
      updateIndex(i, value, 2 * curr + 2, mid, right);
    }
    val[curr] = max(val[2 * curr + 1], val[2 * curr + 2]);
  }
  void updateIndex(int i, int value) { updateIndex(i, value, 0, 0, sz); }

  // int queryIndex(int i,int curr,int left,int right){
  // 	if(right-left==1){
  // 		return val[curr];
  // 	}
  // 	propogate(curr,left,right);
  // 	int mid=(left+right)/2;
  // 	if(i<mid){
  // 		return queryIndex(i,2*curr+1,left,mid);
  // 	}else{
  // 		return queryIndex(i,2*curr+2,mid,right);
  // 	}
  // }
  // int queryIndex(int i){
  // 	return queryIndex(i,0,0,sz);
  // }

  int queryRange(int l, int r, int curr, int left, int right) {
    if (left >= r || right <= l) {
      return NEU;
    }
    // propogate(curr,left,right);
    if (left >= l && right <= r) {
      return val[curr];
    }
    int mid = (left + right) / 2;
    int c1 = queryRange(l, r, 2 * curr + 1, left, mid);
    int c2 = queryRange(l, r, 2 * curr + 2, mid, right);
    return max(c1, c2);
  }
  int queryRange(int l, int r) { return queryRange(l, r, 0, 0, sz); }
};

void solve() {
  int n, k;
  cin >> n >> k;
  vector<int> a(n);
  for (int i = 0; i < n; i++) {
    cin >> a[i];
  }
  segtree st(300001);
  int ans = 1;
  for (int i = 0; i < n; i++) {
    int l = max(0LL, a[i] - k);
    int r = min(300000LL, a[i] + k);
    int val = st.queryRange(l, r + 1);
    ans = max(ans, val + 1);
    st.updateIndex(a[i], val + 1);
  }
  cout << ans << endl;
}

int32_t main() {

  // remove for interactive problems
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);

  solve();
  cerr << "Time : " << 1000 * ((double)clock()) / (double)CLOCKS_PER_SEC
       << "ms\\n";

  return 0;
}


// デバッグ用オプション：-fsanitize=undefined,address

// コンパイラ最適化
#pragma GCC optimize("Ofast")

// インクルードなど
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

// マクロ
// forループ
// 引数は、(ループ内変数,動く範囲)か(ループ内変数,始めの数,終わりの数)、のどちらか
// Dがついてないものはループ変数は1ずつインクリメントされ、Dがついてるものはループ変数は1ずつデクリメントされる
// FORAは範囲for文(使いにくかったら消す)
#define REP(i, n) for (ll i = 0; i < ll(n); i++)
#define REPD(i, n) for (ll i = n - 1; i >= 0; i--)
#define FOR(i, a, b) for (ll i = a; i <= ll(b); i++)
#define FORD(i, a, b) for (ll i = a; i >= ll(b); i--)
#define FORA(i, I) for (const auto &i : I)
// xにはvectorなどのコンテナ
#define ALL(x) x.begin(), x.end()
#define SIZE(x) ll(x.size())
// 定数
#define INF 1000000000000 // 10^12:∞
#define MOD 1000000007    // 10^9+7:合同式の法
#define MAXR 100000       // 10^5:配列の最大のrange
// 略記
#define PB push_back // 挿入
#define MP make_pair // pairのコンストラクタ
#define F first      // pairの一つ目の要素
#define S second     // pairの二つ目の要素

// 以下、素集合と木は同じものを表す
class UnionFind {
public:
  vector<ll> parent; // parent[i]はiの親
  vector<ll> siz;    // 素集合のサイズを表す配列(1で初期化)
  map<ll, vector<ll>>
      group; // 素集合ごとに管理する連想配列(keyはそれぞれの素集合の親、valueはその素集合の要素の配列)

  // コンストラクタ
  UnionFind(ll n) : parent(n), siz(n, 1) {
    // 全ての要素の根が自身であるとして初期化
    for (ll i = 0; i < n; i++) {
      parent[i] = i;
    }
  }

  // データxの属する木の根を取得(経路圧縮も行う)
  ll root(ll x) {
    if (parent[x] == x)
      return x;
    return parent[x] = root(
               parent[x]); // 代入式の値は代入した変数の値なので、経路圧縮できる
  }

  // xとyの木を併合
  void unite(ll x, ll y) {
    ll rx = root(x); // xの根
    ll ry = root(y); // yの根
    if (rx == ry)
      return; // 同じ木にある時
    // 小さい集合を大きい集合へと併合(ry→rxへ併合)
    if (siz[rx] < siz[ry])
      swap(rx, ry);
    siz[rx] += siz[ry];
    parent[ry] = rx; // xとyが同じ木にない時はyの根ryをxの根rxにつける
  }

  // xとyが属する木が同じかを判定
  bool same(ll x, ll y) {
    ll rx = root(x);
    ll ry = root(y);
    return rx == ry;
  }

  // xの素集合のサイズを取得
  ll size(ll x) { return siz[root(x)]; }

  // 素集合をそれぞれグループ化
  void grouping(ll n) {
    // 経路圧縮を先に行う
    REP(i, n) root(i);
    // mapで管理する(デフォルト構築を利用)
    REP(i, n) group[parent[i]].PB(i);
  }
};

signed main() {
  // 入力の高速化用のコード
  // ios::sync_with_stdio(false);
  // cin.tie(nullptr);
  ll n;
  cin >> n;
  vector<ll> ind(n, 0);
  vector<ll> checky(n, 0);
  vector<ll> checkx(n, 0);
  UnionFind uf(n);
  REP(i, n) {
    ll x, y;
    cin >> x >> y;
    checky[x - 1] = y - 1;
    checkx[y - 1] = x - 1;
    ind[x - 1] = i;
  }
  // checkyの中からそれより小さいものを探す(探す順番は値の順番)
  // 値の順番なので、それ以降の省略ができる
  REPD(i, n) {
    ll j = checkx[i];
    while (true) {
      j--;
      if (j < 0)
        break;
      if (i > checky[j]) {
        if (uf.same(ind[checkx[i]], ind[j])) {
          break;
        } else {
          uf.unite(ind[checkx[i]], ind[j]);
        }
      }
    }
  }
  uf.grouping(n);
  REP(i, n) { cout << uf.size(i) << endl; }
}

// デバッグ用オプション：-fsanitize=undefined,address

// コンパイラ最適化
#pragma GCC optimize("Ofast")

// インクルードなど
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

// マクロ
// forループ
// 引数は、(ループ内変数,動く範囲)か(ループ内変数,始めの数,終わりの数)、のどちらか
// Dがついてないものはループ変数は1ずつインクリメントされ、Dがついてるものはループ変数は1ずつデクリメントされる
// FORAは範囲for文(使いにくかったら消す)
#define REP(i, n) for (ll i = 0; i < ll(n); i++)
#define REPD(i, n) for (ll i = n - 1; i >= 0; i--)
#define FOR(i, a, b) for (ll i = a; i <= ll(b); i++)
#define FORD(i, a, b) for (ll i = a; i >= ll(b); i--)
#define FORA(i, I) for (const auto &i : I)
// xにはvectorなどのコンテナ
#define ALL(x) x.begin(), x.end()
#define SIZE(x) ll(x.size())
// 定数
#define INF 1000000000000 // 10^12:∞
#define MOD 1000000007    // 10^9+7:合同式の法
#define MAXR 100000       // 10^5:配列の最大のrange
// 略記
#define PB push_back // 挿入
#define MP make_pair // pairのコンストラクタ
#define F first      // pairの一つ目の要素
#define S second     // pairの二つ目の要素

// 以下、素集合と木は同じものを表す
class UnionFind {
public:
  vector<ll> parent; // parent[i]はiの親
  vector<ll> siz;    // 素集合のサイズを表す配列(1で初期化)
  map<ll, vector<ll>>
      group; // 素集合ごとに管理する連想配列(keyはそれぞれの素集合の親、valueはその素集合の要素の配列)

  // コンストラクタ
  UnionFind(ll n) : parent(n), siz(n, 1) {
    // 全ての要素の根が自身であるとして初期化
    for (ll i = 0; i < n; i++) {
      parent[i] = i;
    }
  }

  // データxの属する木の根を取得(経路圧縮も行う)
  ll root(ll x) {
    if (parent[x] == x)
      return x;
    return parent[x] = root(
               parent[x]); // 代入式の値は代入した変数の値なので、経路圧縮できる
  }

  // xとyの木を併合
  void unite(ll x, ll y) {
    ll rx = root(x); // xの根
    ll ry = root(y); // yの根
    if (rx == ry)
      return; // 同じ木にある時
    // 小さい集合を大きい集合へと併合(ry→rxへ併合)
    if (siz[rx] < siz[ry])
      swap(rx, ry);
    siz[rx] += siz[ry];
    parent[ry] = rx; // xとyが同じ木にない時はyの根ryをxの根rxにつける
  }

  // xとyが属する木が同じかを判定
  bool same(ll x, ll y) {
    ll rx = root(x);
    ll ry = root(y);
    return rx == ry;
  }

  // xの素集合のサイズを取得
  ll size(ll x) { return siz[root(x)]; }

  // 素集合をそれぞれグループ化
  void grouping(ll n) {
    // 経路圧縮を先に行う
    REP(i, n) root(i);
    // mapで管理する(デフォルト構築を利用)
    REP(i, n) group[parent[i]].PB(i);
  }
};

signed main() {
  // 入力の高速化用のコード
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  ll n;
  cin >> n;
  vector<ll> ind(n, 0);
  vector<ll> checky(n, 0);
  vector<ll> checkx(n, 0);
  UnionFind uf(n);
  REP(i, n) {
    ll x, y;
    cin >> x >> y;
    checky[x - 1] = y - 1;
    checkx[y - 1] = x - 1;
    ind[x - 1] = i;
  }
  // checkyの中からそれより小さいものを探す(探す順番は値の順番)
  // checkyの値でsetを作っておいてその中で探す(終わったら削除)
  // 値の順番なので、それ以降の省略ができる
  set<ll> set_checky;
  REP(i, n) set_checky.insert(i);
  REPD(i, n) {
    // yの大きいところから探す(見つかったらbreak)
    // setないはxの順番
    auto j = set_checky.lower_bound(checkx[i]);
    if (j == set_checky.begin()) {
      set_checky.erase(checkx[i]);
      continue;
    }
    // cout<<2<<endl;
    j--;
    while (true) {
      // cout<<4<<endl;
      if (uf.same(ind[checkx[i]], ind[*j])) {
        // cout<<4<<endl;
        if (ind[checkx[i]] != ind[*j])
          break;
      } else {
        uf.unite(ind[checkx[i]], ind[*j]);
      }
      if (j == set_checky.begin())
        break;
      j--;
      // cout<<1<<endl;
    }
    /*
    REPD(j,checkx[i]){
        if(i>checky[j]){
            if(uf.same(ind[checkx[i]],ind[j])){
                break;
            }else{
                uf.unite(ind[checkx[i]],ind[j]);
            }
        }
    }
    */
    set_checky.erase(checkx[i]);
  }
  uf.grouping(n);
  REP(i, n) { cout << uf.size(i) << endl; }
}


#include <bits/stdc++.h>
using namespace std;
int n, b[200005], tot, v[8000005], h[8000005], ans[200005], ww, s;
vector<int> vec;
struct P {
  int x, y, id;
} a[200005];
struct E {
  int to, next;
} e[24000005];
void A(int x, int y) { e[++ww] = {y, h[x]}, h[x] = ww; }
void dfs(int x) {
  if (!x || v[x])
    return;
  v[x] = 1;
  if (x <= n)
    vec.push_back(x), s++;
  for (int i = h[x]; i; i = e[i].next)
    dfs(e[i].to);
}
struct SEGMENT {
  int c[8000005][2], rt;
  bool is;
  void Ins(int &p, int l, int r, int x, int y) {
    int q = ++tot;
    c[q][0] = c[p][0], c[q][1] = c[p][1];
    if (!is)
      A(q, p);
    else
      A(p, q);
    p = q;
    if (l == r) {
      if (!is)
        A(p, y);
      else
        A(y, p);
      return;
    }
    int mid = (l + r) / 2;
    if (!is) {
      if (x <= mid)
        A(p, c[p][1]), Ins(c[p][0], l, mid, x, y), A(p, c[p][0]);
      else
        A(p, c[p][0]), Ins(c[p][1], mid + 1, r, x, y), A(p, c[p][1]);
    } else {
      if (x <= mid)
        A(c[p][1], p), Ins(c[p][0], l, mid, x, y), A(c[p][0], p);
      else
        A(c[p][0], p), Ins(c[p][1], mid + 1, r, x, y), A(c[p][1], p);
    }
  }
  void Link(int p, int l, int r, int x, int y) {
    if (!p)
      return;
    if (r <= x) {
      if (!is)
        return A(y, p), void();
      else
        return A(p, y), void();
    }
    int mid = (l + r) / 2;
    Link(c[p][0], l, mid, x, y);
    if (x > mid)
      Link(c[p][1], mid + 1, r, x, y);
  }
} q1, q2;
int main() {
  cin >> n, tot = n;
  for (int i = 1; i <= n; i++)
    cin >> a[i].x >> a[i].y, b[i] = a[i].y, a[i].id = i;
  sort(b + 1, b + n + 1);
  for (int i = 1; i <= n; i++)
    a[i].y = lower_bound(b + 1, b + n + 1, a[i].y) - b;
  sort(a + 1, a + n + 1,
       [](P i, P j) { return i.x ^ j.x ? i.x < j.x : i.y < j.y; });
  q2.is = 1;
  for (int i = 1; i <= n; i++) {
    q1.Link(q1.rt, 1, n, a[i].y, i);
    q1.Ins(q1.rt, 1, n, a[i].y, i);
    q2.Link(q2.rt, 1, n, a[i].y, i);
    q2.Ins(q2.rt, 1, n, a[i].y, i);
  }
  for (int i = 1; i <= n; i++) {
    if (!v[i]) {
      s = 0, vec.clear(), dfs(i);
      for (int j : vec)
        ans[a[j].id] = s;
    }
  }
  for (int i = 1; i <= n; i++)
    cout << ans[i] << '\\n';
  return 0;
}

#include <bits/stdc++.h>
using namespace std;
int n, b[200005], tot, v[10000005], h[10000005], ans[200005], ww, s;
vector<int> vec;
struct P {
  int x, y, id;
} a[200005];
struct E {
  int to, next;
} e[28000005];
void A(int x, int y) { e[++ww] = {y, h[x]}, h[x] = ww; }
void dfs(int x) {
  if (!x || v[x])
    return;
  v[x] = 1;
  if (x <= n)
    vec.push_back(x), s++;
  for (int i = h[x]; i; i = e[i].next)
    dfs(e[i].to);
}
struct SEGMENT {
  int c[10000005][2], rt;
  bool is;
  void Ins(int &p, int l, int r, int x, int y) {
    int q = ++tot;
    c[q][0] = c[p][0], c[q][1] = c[p][1];
    if (!is)
      A(q, p);
    else
      A(p, q);
    p = q;
    if (l == r) {
      if (!is)
        A(p, y);
      else
        A(y, p);
      return;
    }
    int mid = (l + r) / 2;
    if (!is) {
      if (x <= mid)
        A(p, c[p][1]), Ins(c[p][0], l, mid, x, y), A(p, c[p][0]);
      else
        A(p, c[p][0]), Ins(c[p][1], mid + 1, r, x, y), A(p, c[p][1]);
    } else {
      if (x <= mid)
        A(c[p][1], p), Ins(c[p][0], l, mid, x, y), A(c[p][0], p);
      else
        A(c[p][0], p), Ins(c[p][1], mid + 1, r, x, y), A(c[p][1], p);
    }
  }
  void Link(int p, int l, int r, int x, int y) {
    if (!p)
      return;
    if (r <= x) {
      if (!is)
        return A(y, p), void();
      else
        return A(p, y), void();
    }
    int mid = (l + r) / 2;
    Link(c[p][0], l, mid, x, y);
    if (x > mid)
      Link(c[p][1], mid + 1, r, x, y);
  }
} q1, q2;
int main() {
  cin >> n, tot = n;
  for (int i = 1; i <= n; i++)
    cin >> a[i].x >> a[i].y, b[i] = a[i].y, a[i].id = i;
  sort(b + 1, b + n + 1);
  for (int i = 1; i <= n; i++)
    a[i].y = lower_bound(b + 1, b + n + 1, a[i].y) - b;
  sort(a + 1, a + n + 1,
       [](P i, P j) { return i.x ^ j.x ? i.x < j.x : i.y < j.y; });
  q2.is = 1;
  for (int i = 1; i <= n; i++) {
    q1.Link(q1.rt, 1, n, a[i].y, i);
    q1.Ins(q1.rt, 1, n, a[i].y, i);
    q2.Link(q2.rt, 1, n, a[i].y, i);
    q2.Ins(q2.rt, 1, n, a[i].y, i);
  }
  for (int i = 1; i <= n; i++) {
    if (!v[i]) {
      s = 0, vec.clear(), dfs(i);
      for (int j : vec)
        ans[a[j].id] = s;
    }
  }
  for (int i = 1; i <= n; i++)
    cout << ans[i] << '\\n';
  return 0;
}