/*
    Author:zeke

    pass System Test!
    GET AC!!
*/
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using ll = long long;
using ld = long double;
using namespace std;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define all(x) (x).begin(), (x).end()
#define rep3(var, min, max) for (ll(var) = (min); (var) < (max); ++(var))
#define repi3(var, min, max) for (ll(var) = (max)-1; (var) + 1 > (min); --(var))
#define Mp(a, b) make_pair((a), (b))
#define F first
#define S second
#define Icin(s) \
    ll(s);      \
    cin >> (s);
#define Scin(s) \
    ll(s);      \
    cin >> (s);
template <class T>
bool chmax(T& a, const T& b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <class T>
bool chmin(T& a, const T& b) {
    if (b < a) {
        a = b;
        return 1;
    }
    return 0;
}
typedef pair<ll, ll> P;
typedef vector<ll> V;
typedef vector<V> VV;
typedef vector<P> VP;
ll mod = 1e9 + 7;
ll MOD = 1e9 + 7;
ll INF = 1e18;
#define int ll
// cout << "Case #" << index << " :IMPOSSIBLE";
struct SegmentTree {
private:
    int n;
    vector<int> node;
    //int nとvector<int> nodeの2つを変数に持つ。
    //nは扱う配列の要素数で、nodeはまさにsegtree本体

public:
    //初期化処理。segtreeを使うときは最初にこれを宣言する。
    SegmentTree(vector<int> v) {
        int sz = v.size(); //vは扱う配列の長さ
        n = 1; while(n < sz) n *= 2; //nはvの配列を全て入れるために必要なseg treeの葉の数
        node.resize(2*n-1, INF); //★演算によって単位元を変える。segtreeでは全部で2n-1の配列が必要。
        //最小値を求めるのであれば、最初は単位元であるINFで初期化しておく
        //例えばv.size()が2のべき乗で無かった場合は、最終的な計算結果に影響のないような単位元の葉を用意しておく必要がある
        for(int i=0; i<sz; i++) node[i+n-1] = v.at(i); //segtreeの葉の部分に扱う配列を埋め込む
        for(int i=n-2; i>=0; i--) node[i] = min(node[2*i+1],node[2*i+2]); 
        //★演算によって変える場所　segtreeを作る(注目しているnode iの子ノードを見て二項演算をして、node iの値を決定する)
    }

    void update(int x, int val) {
        //一点更新処理。x番目の要素をvalに変更する
        x += (n - 1); //配列のx番目の要素を更新しようとするとき、segtreeで対応する要素はx+n-1番目である
        node[x] = val; //segtree上で値を更新
        while(x > 0) { //葉から根に向かってsegtreeの要素を更新していく
            x = (x - 1) / 2;
            node[x] = min(node[2*x+1],node[2*x+2]); //★演算によって変える
        }
    }

    int getor(int a, int b, int k=0, int l=0, int r=-1) {
        //区間取得処理。求めたいのは区間[a,b)の中で演算しつづけた結果(たとえばこの区間の最小値)
        //ノードkは元の配列でいうとどの区間をカバーしているか？を表すindex
        if(r < 0) r = n; //最初に呼び出す時はノードk=0はsegtreeの根なので区間は[0,n)を指す
        if(r <= a || b <= l) return INF;
        //★演算によって変える 今のノードが求める区間と無関係の場合は、
        //最終的な答えに影響しない単位元(最小値を求めたい場合は単位元はINF)を返す
        if(a <= l && r <= b) return node[k];
        //今見ている区間[l,r)が答えを求めたい区間[a,b)に完全に含まれるなら
        //この区間について演算し続けた結果(=node[k];例えば最小値)を返す

        //上記に当てはまらない場合
        //kの子ノードを見に行って、再帰的に処理を行う k=0の場合はノード1と2を見る
        int vl = getor(a, b, 2*k+1, l, (l+r)/2);
        //kの子ノード(left)の子孫のうち、求めたい区間に含まれる要素について演算し続けた結果を返す
        int vr = getor(a, b, 2*k+2, (l+r)/2, r);
        //kの子ノード(right)の子孫のうち、求めたい区間に含まれる要素について演算し続けた結果を返す
        return min(vl,vr); //★演算によって変える場所 子ノードの子孫のうち、演算しつづけた結果を返す
    }
};
signed main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
    ll n,k;
    cin>>n>>k;
    V vec(n);
    rep(i,n)cin>>vec[i];
    V dp(3e5+1);
    SegmentTree tree(dp);
    rep(i,n){
        ll Max=-tree.getor(max(0LL,vec[i]-k),min((ll)3e5+1,vec[i]+k+1));
        //cout<<max(0LL,vec[i]-k)<<" "<<min((ll)3e5,vec[i]+k)<<endl;
        tree.update(vec[i],-(Max+1));
       // cout<<Max<<endl;
    }
    cout<<-tree.getor(0,3e5+1)<<endl;
}


Measured memory_bytes: 18524