// Slower C++ solution:
#include <bits/stdc++.h>

//#include <atcoder/all>

#define rep(i, a) for (int i = (int)0; i < (int)a; ++i)

#define rrep(i, a) for (int i = (int)a - 1; i >= 0; --i)

#define REP(i, a, b) for (int i = (int)a; i < (int)b; ++i)

#define RREP(i, a, b) for (int i = (int)a - 1; i >= b; --i)

#define pb push_back

#define eb emplace_back

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

#define rall(x) x.rbegin(), x.rend()

#define popcount __builtin_popcount

using ll = long long;

constexpr ll mod = 1e9 + 7;

constexpr ll INF = 1LL << 60;



// #pragma GCC target("avx2")

// #pragma GCC optimize("O3")

// #pragma GCC optimize("unroll-loops")

template <class T>

inline bool chmin(T &a, T b)

{

	if (a > b)

	{

		a = b;

		return true;

	}

	return false;

}

template <class T>

inline bool chmax(T &a, T b)

{

	if (a < b)

	{

		a = b;

		return true;

	}

	return false;

}



ll gcd(ll n, ll m)

{

	ll tmp;

	while (m != 0)

	{

		tmp = n % m;

		n = m;

		m = tmp;

	}

	return n;

}



ll lcm(ll n, ll m)

{

	return abs(n) / gcd(n, m) * abs(m); //gl=xy

}



using namespace std;

//using namespace atcoder;



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;

    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);

  }



  Monoid operator[](const int &k) const {

    return seg[k + sz];

  }



  template< typename C >

  int find_subtree(int a, const C &check, Monoid &M, bool type) {

    while(a < sz) {

      Monoid nxt = type ? f(seg[2 * a + type], M) : f(M, seg[2 * a + type]);

      if(check(nxt)) a = 2 * a + type;

      else M = nxt, a = 2 * a + 1 - type;

    }

    return a - sz;

  }





  template< typename C >

  int find_first(int a, const C &check) {

    Monoid L = M1;

    if(a <= 0) {

      if(check(f(L, seg[1]))) return find_subtree(1, check, L, false);

      return -1;

    }

    int b = sz;

    for(a += sz, b += sz; a < b; a >>= 1, b >>= 1) {

      if(a & 1) {

        Monoid nxt = f(L, seg[a]);

        if(check(nxt)) return find_subtree(a, check, L, false);

        L = nxt;

        ++a;

      }

    }

    return -1;

  }



  template< typename C >

  int find_last(int b, const C &check) {

    Monoid R = M1;

    if(b >= sz) {

      if(check(f(seg[1], R))) return find_subtree(1, check, R, true);

      return -1;

    }

    int a = sz;

    for(b += sz; a < b; a >>= 1, b >>= 1) {

      if(b & 1) {

        Monoid nxt = f(seg[--b], R);

        if(check(nxt)) return find_subtree(b, check, R, true);

        R = nxt;

      }

    }

    return -1;

  }

};





void solve(){

	ll n,k;

	cin>>n>>k;

	vector<ll>a(n);

	rep(i,n)cin>>a[i];

	vector<ll>v(n,1);

	SegmentTree<ll>seg(300005,[](ll a,ll b){return max(a,b);},0LL);

	rep(i,n){

		seg.update(a[i],1);

	}

	for(int i=n-1;i>=0;--i){

		v[i]=seg.query(max(0LL,a[i]-k),min(300000LL,a[i]+k)+1)+v[i];

		seg.update(a[i],v[i]);

	}

	ll ans=0;

	rep(i,n){

		chmax(ans,v[i]);

	}

	cout<<ans-1;

}



int main()

{

	ios::sync_with_stdio(false);

	cin.tie(nullptr);

	cout << fixed << setprecision(15);

	solve();

	return 0;

}


// Faster C++ solution for the same problem (measured speedup: 1.8472269617166297x):
#include <bits/stdc++.h>

// #include <atcoder/all>

#define rep(i, a) for (int i = (int)0; i < (int)a; ++i)

#define rrep(i, a) for (int i = (int)a - 1; i >= 0; --i)

#define REP(i, a, b) for (int i = (int)a; i < (int)b; ++i)

#define RREP(i, a, b) for (int i = (int)a - 1; i >= b; --i)

#define pb push_back

#define eb emplace_back

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

#define rall(x) x.rbegin(), x.rend()

#define popcount __builtin_popcount

using ll = long long;

constexpr ll mod = 1e9 + 7;

constexpr ll INF = 1LL << 60;



// #pragma GCC target("avx2")

// #pragma GCC optimize("O3")

// #pragma GCC optimize("unroll-loops")

template <class T>

inline bool chmin(T &a, T b)

{

	if (a > b)

	{

		a = b;

		return true;

	}

	return false;

}

template <class T>

inline bool chmax(T &a, T b)

{

	if (a < b)

	{

		a = b;

		return true;

	}

	return false;

}



ll gcd(ll n, ll m)

{

	ll tmp;

	while (m != 0)

	{

		tmp = n % m;

		n = m;

		m = tmp;

	}

	return n;

}



ll lcm(ll n, ll m)

{

	return abs(n) / gcd(n, m) * abs(m); //gl=xy

}



using namespace std;

// using namespace atcoder;



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;

    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);

  }



  Monoid operator[](const int &k) const {

    return seg[k + sz];

  }



  template< typename C >

  int find_subtree(int a, const C &check, Monoid &M, bool type) {

    while(a < sz) {

      Monoid nxt = type ? f(seg[2 * a + type], M) : f(M, seg[2 * a + type]);

      if(check(nxt)) a = 2 * a + type;

      else M = nxt, a = 2 * a + 1 - type;

    }

    return a - sz;

  }





  template< typename C >

  int find_first(int a, const C &check) {

    Monoid L = M1;

    if(a <= 0) {

      if(check(f(L, seg[1]))) return find_subtree(1, check, L, false);

      return -1;

    }

    int b = sz;

    for(a += sz, b += sz; a < b; a >>= 1, b >>= 1) {

      if(a & 1) {

        Monoid nxt = f(L, seg[a]);

        if(check(nxt)) return find_subtree(a, check, L, false);

        L = nxt;

        ++a;

      }

    }

    return -1;

  }



  template< typename C >

  int find_last(int b, const C &check) {

    Monoid R = M1;

    if(b >= sz) {

      if(check(f(seg[1], R))) return find_subtree(1, check, R, true);

      return -1;

    }

    int a = sz;

    for(b += sz; a < b; a >>= 1, b >>= 1) {

      if(b & 1) {

        Monoid nxt = f(seg[--b], R);

        if(check(nxt)) return find_subtree(b, check, R, true);

        R = nxt;

      }

    }

    return -1;

  }

};





void solve(){

  int n,k;

	cin>>n>>k;

	vector<int>a(n);

	for(auto &x:a)cin>>x;

	SegmentTree<int>seg(300010,[](int a,int b){return max(a,b);},0);

	vector<int>dp(n);

	rep(i,n){

		int lb=max(0,a[i]-k);

		int ub=min(300000,a[i]+k);

		dp[i]=seg.query(lb,ub+1)+1;

		seg.update(a[i],dp[i]);

	}



	int ans=seg.query(0,300001);

	cout<<ans<<"\n";

}



int main()

{

	ios::sync_with_stdio(false);

	cin.tie(nullptr);

	cout << fixed << setprecision(15);

	solve();

	return 0;

}