#include<bits/stdc++.h>
#define int long long
#define endl "\n"
#define FastIO ios_base::sync_with_stdio(false); cin.tie(NULL);
using namespace std;
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
// #define ordered_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>
//less_equal to ordered multiset
class SegmentTree {
private:
    vector<int> tree;
    vector<int> arr;
    int n;

    // Build the segment tree recursively
    void build(int node, int start, int end)
    {
        if (start == end)
        {
            tree[node] = arr[start];
        }
        else
        {
            int mid = (start + end) / 2;
            build(2 * node + 1, start, mid);
            build(2 * node + 2, mid + 1, end);
            tree[node] = max(tree[2 * node + 1] , tree[2 * node + 2]);
        }
    }

    // Update the value at index 'idx' to 'val' recursively
    void update(int node, int start, int end, int idx, int val) {
        if (start == end)
        {
            arr[idx] = val;
            tree[node] = val;
        }
        else
        {
            int mid = (start + end) / 2;
            if (idx >= start && idx <= mid)
            {
                update(2 * node + 1, start, mid, idx, val);
            }
            else
            {
                update(2 * node + 2, mid + 1, end, idx, val);
            }
            tree[node] = max(tree[2 * node + 1] , tree[2 * node + 2]);
        }
    }

    // Query the sum in the range [l, r] recursively
    int query(int node, int start, int end, int l, int r)
    {
        if(r < start || l > end)
        {
            return 0; // Out of range
        }
        if(l <= start && r >= end)
        {
            return tree[node]; // Current segment is fully within the query range
        }
        int mid = (start + end) / 2;
        int left = query(2 * node + 1, start, mid, l, r);
        int right = query(2 * node + 2, mid + 1, end, l, r);
        return max(left , right);
    }

public:
    // Constructor to initialize the segment tree with an array
    SegmentTree(vector<int>& input)
    {
        n = input.size();
        arr = input;
        tree.resize(4 * n); // Assuming a maximum size for the tree
        build(0, 0, n - 1);
    }

    // Update the value at index 'idx' to 'val'
    void update(int idx, int val)
    {
        update(0, 0, n - 1, idx, val);
    }

    // Query the sum in the range [l, r]
    int query(int l, int r)
    {
        return query(0, 0, n - 1, l, r);
    }
};

void solve()
{
    int n,d;
    cin>>n>>d;
    const int N=5e5+10;
    vector<int> v(n);
    vector<int> dp(N+5,0);
    for(int i=0;i<n;i++)
    {
        cin>>v[i];
    }
    SegmentTree st(dp);
    int ans=0;
    for(int i=0;i<n;i++)
    {
        int lb=max(0LL,v[i]-d),ub=min(N,v[i]+d);
        int mx=st.query(lb,ub);
        dp[v[i]]=max(dp[v[i]],mx+1);
        st.update(v[i],dp[v[i]]);
        ans=max(ans,dp[v[i]]);
    }
    cout<<ans<<endl;
}

signed main(){
    FastIO;
    // #ifndef ONLINE_JUDGE
    //     freopen("input.txt", "r", stdin);
    //     freopen("output.txt", "w", stdout);
    // #endif
    int t=1;
    // cin>>t;
    for(int i=1;i<=t;i++)
    {
        //cout<<"Case #"<<i<<": ";
        solve();
    }
    return 0;
}