#include <bits/stdc++.h>
#if __has_include("debug.h")
#include "debug.h"
#endif
using namespace std;

typedef long long ll;
typedef pair<ll,ll> ii;
typedef vector<ll> vi;
typedef vector<ii> vii;

#define pb push_back
#define ff first
#define ss second
#define rep(i, a, b) for (ll i = a; i < b; ++i)
#define rep_(i, a, b) for (ll i = a; i > b; --i)
#define endl '\n'

const ll maxn = 3e5 + 5;

// -------------- Arithmetic --------------
const ll mod = 1e9 + 7;

ll power(ll x, ll y, ll m) {
	ll ans = 1;
	x = x % mod;
	if (x == 0) return 0;
	while (y > 0) {
		if (y & 1) ans = (ans * x) % m;
		y = y >> 1;
		x = (x * x) % m;
	}
	return ans;
}

ll mod_inv(ll a) {return power(a, mod - 2, mod);}

ll add(ll a, ll b) {return (((a + b) % mod) + mod) % mod;}
ll sub(ll a, ll b) {return (((a - b) % mod) + mod) % mod;}
ll mul(ll a, ll b) {return (((a * b) % mod) + mod) % mod;}
ll div(ll a, ll b) {return mul(a, mod_inv(b));}

// -------------- Code --------------

ll n, k;
ll a[maxn];

class SegmentTree { // the segment tree is stored like a heap array
	public: vi st, A; // recall that vi is: typedef vector<ll> vi;
		ll left (ll p) { return p << 1; } // same as binary heap operations
		ll right(ll p) { return (p << 1) + 1; }
		
		void build(ll p, ll L, ll R) { // O(n)
			if (L == R) // as L == R, either one is fine
				st[p] = L; // store the index
			else { // recursively compute the values
				build(left(p) , L , (L + R) / 2);
				build(right(p), (L + R) / 2 + 1, R );
				ll p1 = st[left(p)], p2 = st[right(p)];
				st[p] = (A[p1] >= A[p2]) ? p1 : p2;//CHANGE: > -> < for rMq -> rmq
			} 
		}
		
		ll rmq(ll p, ll L, ll R, ll i, ll j) { // O(log n)
			if (i > R || j < L) return -1; // current segment outside query range
			if (L >= i && R <= j) return st[p]; // inside query range
			// compute the min position in the left and right part of the llerval
			ll p1 = rmq(left(p) , L , (L+R) / 2, i, j);
			ll p2 = rmq(right(p), (L+R) / 2 + 1, R , i, j);
			if (p1 == -1) return p2; // if we try to access segment outside query
			if (p2 == -1) return p1; // same as above
			return (A[p1] >= A[p2]) ? p1 : p2; // as in build routine //CHANGE: > -> < for rMq -> rmq
		}

		void update(ll p, ll L, ll R, ll i) { // O(log n)
			if (i > R || i < L) return; // current segment outside query range
			if (L == R) return; // inside query range
			// compute the min position in the left and right part of the llerval
			if (A[i] > A[st[p]]) st[p] = i;
			update(left(p) , L , (L+R) / 2, i);
			update(right(p), (L+R) / 2 + 1, R , i);
		}

		SegmentTree() {
			A.assign(maxn, 0);
			st.assign(4 * maxn, 0); // create large enough vector of zeroes
			build(1, 0, maxn - 1); // recursive build
		}
		
		ll rmq(ll i, ll j) { return rmq(1, 0, maxn - 1, i, j); } // overloading

		void update(ll i, ll ai) { A[i] = ai; update(1, 0, maxn - 1, i); } // overloading
};

void solve() {
	cin >> n >> k;
	rep(i, 0, n) cin >> a[i];
	SegmentTree seg;
	ll ans = 0;
	rep(i, 0, n) {
		seg.update(a[i], 1 + seg.A[seg.rmq(max(0ll, a[i] - k), min(maxn, a[i] + k))]);
		ans = max(ans, seg.A[a[i]]);
	}
	cout << ans << endl;
}

void aux() {
}

int main() {
	ios_base::sync_with_stdio(false); cin.tie(NULL);
	cout << fixed << setprecision(10);
	aux();
	ll _ = 1;
	// cin >> _;
	while(_--) {
		solve();
	}
	return 0;
}

Measured memory_bytes: 17140