#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")

#include<bits/stdc++.h>

using namespace std;
#define ll long long
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define ins insert
#define ull unsigned long long
#define rep(i, begin, end) for (__typeof(end) i = (begin) - ((begin) > (end)); i != (end) - ((begin) > (end)); i += 1 - 2 * ((begin) > (end)))
#define ff first
#define ss second
#define fast ios::sync_with_stdio(0) , cin.tie(0) , cout.tie(0);
#define nl "\n"
#define sz(a) (int)(a).size()
#define all(a) (a).begin(),(a).end()
#define fl(a,x) memset(a,x,sizeof(a));
#define pt(a,x) cout << get<x>(a) << " " ;
#define mt make_tuple
#define vec vector

#define int long long

const int mod = (int) 1e9 + 7 ;
const int MOD = (int) 998244353 ;
const int INF = (int) 1e18 ;

typedef vector<int> vii;
typedef pair<int,int> pii;
typedef vector<pii> vpi;
typedef vector<vector<int> > vv;

#define error(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); }

void err(istream_iterator<string> it) {}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
	cerr << *it << " = " << a << endl;
	err(++it, args...);
}


template <typename T> 
class SegTree {
	int n;
	T CNST ;  
	vector<T> tree, lazyAdd, lazySet;
	vector<bool> isSet; 
	int type;
	// 0 - sum 
	// 1 - min
	// 2 - max
	// 3 - gcd
	// 4 - lcm
	// 5 - xor 
public :
	
	SegTree(int x, string str) {
		n = x ;
		tree.resize(4*n+5) ;
		lazyAdd.resize(4*n+5) ;
		lazySet.resize(4*n+5) ;
		isSet.resize(4*n+5) ; 
		
		if(str == "sum") type = 0 ; 
		else if(str == "min") type = 1 ;
		else if(str == "max") type = 2 ;
		else if(str == "gcd") type = 3 ; 
		else if(str == "lcm") type = 4 ;
		else if(str == "xor") type = 5 ;
		
		if(type == 0 or type == 3 or type == 5) CNST = 0 ; 
		if(type == 2 ) CNST = numeric_limits<T>::min() ; 
		if(type == 1 ) CNST = numeric_limits<T>::max() ;
		if(type == 4 ) CNST = 1 ; 
	}

	T merge(T a, T b) {
		if(type == 0 ) return a + b ; 
		else if(type == 1 ) return min(a,b) ;
		else if(type == 2 ) return max(a,b) ;
		else if(type == 3 ) return __gcd(a,b) ;
		else if(type == 4 ) return (a * b / __gcd(a,b)) ;
		else return a ^ b ; 
	}

	void _build(int node,int start,int end, vector<T> &arr) {
		if(start == end) {
			tree[node] = arr[start] ;
			return ;
		}
		int mid = (start + end) >> 1;
		_build(2*node, start, mid, arr) ;
		_build(2*node+1, mid+1, end, arr) ;
		tree[node] = merge(tree[2*node], tree[2*node+1]);
	}

	void build(vector<T> &arr) {
		_build(1,1,n,arr) ;
	}

	void _update(int node, int start, int end,int idx, T val) {
		if(start == end) {
			tree[node] = val ;
			return ;
		}
		int mid = (start + end) >> 1 ;
	
		if(start <= idx and idx <= mid) _update(2*node, start, mid, idx, val) ;
		else _update(2*node+1, mid+1, end, idx, val) ;
		tree[node] = merge(tree[2*node], tree[2*node+1]);
	}

	void update(int x, T val) {
		_update(1,1,n,x,val) ;
	}

	void reset(int node) {
		lazySet[node] = 0 ; 
		lazyAdd[node] = 0 ; 
		isSet[node] = 0 ; 
	}

	void compose(int par,int child) {
		if(isSet[par]) {
			lazySet[child] = lazySet[par] ;
			lazyAdd[child] = lazyAdd[par] ;
			isSet[child] = true;  
		}
		else lazyAdd[child] += lazyAdd[par]; 
	}

	void applyAgg(int node,int start, int end) {
		if(isSet[node]) tree[node] = (end-start + 1) * lazySet[node]; 
		tree[node] += (end - start + 1) * lazyAdd[node] ;

		if(start != end ) {
			compose(node, 2*node) ;
			compose(node, 2*node + 1) ;
		}  

		reset(node) ;	
	}

	void _updateRange(int node,int start,int end,int l, int r,T val, int t) {

		if(start > end or start > r or end < l ) return ; 

		if(start >= l and end <= r) {
			if(t == 1) lazyAdd[node] += val; 
			else {
				isSet[node] = 1; 
				lazySet[node] = val ;
				lazyAdd[node] = 0 ;
			}
			return ; 
		}

		applyAgg(node,start,end) ;

		int mid = (start + end) >> 1 ;

		_updateRange(2*node, start, mid, l, r, val, t) ;
		_updateRange(2*node + 1, mid+1, end, l, r, val, t) ;

		applyAgg(2*node,start,mid) ;
		applyAgg(2*node+1,mid+1,end) ;

		tree[node] = merge(tree[2*node], tree[2*node+1]) ;
	}

	void updateRange(int l,int r, T val, string str) {
		int t = (str == "add" ? 1 : 2 ) ;
		_updateRange(1,1,n,l,r,val,t) ;
	}

	T _query(int node, int start,int end,int l, int r) {
		if(r < start or l > end ) return CNST;
		applyAgg(node,start,end) ;
		if(l <= start and end <= r) return tree[node] ;
		int mid = (start + end) >> 1 ;
		return merge(_query(2*node,start, mid, l,r), _query(2*node+1,mid+1,end,l,r));
	}

	T query(int l, int r) {
		return _query(1,1,n,l,r) ;
	}
};


void solve() {
	int n,k; cin >> n >> k ;
	
	vii a(n+1); rep(i,1,n+1) cin >> a[i] ;

	int N = 3e5 + 5 ; 
	SegTree<int> S(N,"max");

	rep(i,1,n+1) {
		int mx = S.query(max(0ll,a[i]-k),min(N,a[i]+k));
		mx = max(mx,0ll); 
		S.update(a[i], mx+1) ; 
	}

	cout << S.query(1,N) ; 
}

int32_t main() {

#ifdef LOCAL
    freopen("error.txt", "w", stderr);
#endif

    fast;

	// int t; cin >> t; while(t--)
		solve() ;

	// cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
	return 0;
}