#include<bits/stdc++.h>
#define ll long long
const int md=998244353;
#define fast                          \
    ios_base::sync_with_stdio(false); \
    cin.tie(0);                       \
    cout.tie(0);
/* VECTORS */
#define pb push_back
#define g(v,i,j) get<i>(v[j])
#define co(v,x) count(v.begin(),v.end(),x)
#define mxe(v) *max_element(v.begin(),v.end())
#define mne(v) *min_element(v.begin(),v.end())
#define vi vector<int>
#define vll vector<ll>
#define srt(v) sort(v.begin(),v.end())
#define rsrt(v) sort(v.begin(),v.end(),greater<int>())
/* INPUT/OUTPUT*/
#define pr printf
#define sc scanf
#define pi(a) printf("%d\n",a)
#define pll(a) printf("%lld\n",a)
#define si(a) scanf("%d",&a)
#define sll(a) scanf("%lld",&a)
/* LOOPS*/
#define fi(i,a,b) for(int i=a;i<b;i++)
#define fll(i,a,b) for(ll i=a;i<b;i++)
using namespace std;
using namespace std::chrono;
ll pw(ll a, ll b)
{
    ll c=1,m=a;
    while (b)
    {
        if(b&1) c=(c * m);
        m=(m*m);
        b/=2;
    }
    return c;
}
ll pwmd(ll a,ll b)
{
    ll c=1,m=a;
    while(b)
    {
        if(b&1) c=(c*m)%md;
        m=(m*m)%md;
        b/=2;
    }
    return c;
}
ll modinv(ll n)
{
    return pwmd(n, md - 2);
}
ll inverse(ll i){
    if(i==1) return 1;
    return (md - ((md/i)*inverse(md%i))%md+md)%md;
}
ll ceel(ll a,ll b)
{
    if(a%b==0) return a/b;
    else return a/b+1;
}
ll my_log(ll n, ll b)
{
    ll i=1;
    ll ans=0;
    while(1)
    {
        if(i>n)
        {
            ans--;
            break;
        }
        if(i==n) break;
        i*=b;
        ans++;
    }
    return ans;
}
bool sortbysec(const pair<ll,ll> &a,
              const pair<ll,ll> &b)
{
    return (a.second < b.second);
}
   /* auto start = high_resolution_clock::now();
    auto stop = high_resolution_clock::now();
    auto duration = duration_cast<microseconds>(stop - start);
    cerr << "Time taken: "
         << duration.count()<< "ms" <<"\n";*/
ll gcd(ll a, ll b)
{
    if (b == 0)
        return a;
    return gcd(b, a % b);

}
vector<char> capl={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
vector<char> sml={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
string conv(ll a)
{
    string b;
    ll e=2;
    ll c=my_log(a,e);
    c++;
    b='1';
    for(int i=0;i<c-1;i++)
    {
        ll k=a>>(c-2-i);
        if(k&1) b+='1';
        else b+='0';
    }
    if(a==0) return "0";
    return b;
}
ll mysqt(ll a)
{
    ll ans=1;
    while(ans*ans<=a) ans++;
    ans--;
    return ans;
}
bool isprime(int p)
{
    int i=2;
    while(i<=sqrt(p))
    {
        if(p%i==0)
        {
            return false;
        }
        i++;
    }
    return true;
}
int getMid(int s, int e)
{
    return s + (e - s) / 2;
}

/*  A recursive function to get the sum of
    values in given range of the array.
    The following are parameters for this
    function.

    st       -> Pointer to segment tree
    node     -> Index of current node in
                the segment tree .
    ss & se  -> Starting and ending indexes
                of the segment represented
                by current node, i.e., st[node]
    l & r    -> Starting and ending indexes
                of range query */
int MaxUtil(int* st, int ss, int se, int l,
            int r, int node)
{
    // If segment of this node is completely
    // part of given range, then return
    // the max of segment
    if (l <= ss && r >= se)
        return st[node];

    // If segment of this node does not
    // belong to given range
    if (se < l || ss > r)
        return -1;

    // If segment of this node is partially
    // the part of given range
    int mid = getMid(ss, se);

    return max(MaxUtil(st, ss, mid, l, r,
                       2 * node + 1),
               MaxUtil(st, mid + 1, se, l,
                       r, 2 * node + 2));
}

/* A recursive function to update the nodes which
   have the given index in their range. The following
   are parameters st, ss and se are same as defined
   above index -> index of the element to be updated.*/
void updateValue(int arr[], int* st, int ss, int se,
                 int index, int value, int node)
{
    if (index < ss || index > se)
    {
        cout << "Invalid Input" << endl;
        return;
    }

    if (ss == se)
    {
        // update value in array and in segment tree
        arr[index] = value;
        st[node] = value;
    }
    else {
            int mid = getMid(ss, se);

            if (index >= ss && index <= mid)
                updateValue(arr, st, ss, mid, index,
                            value, 2 * node + 1);
            else
                updateValue(arr, st, mid + 1, se,
                            index, value, 2 * node + 2);

            st[node] = max(st[2 * node + 1],
                       st[2 * node + 2]);
    }
    return;
}

// Return max of elements in range from
// index l (query start) to r (query end).
int getMax(int* st, int n, int l, int r)
{
    // Check for erroneous input values
    if (l < 0 || r > n - 1 || l > r)
    {
        printf("Invalid Input");
        return -1;
    }

    return MaxUtil(st, 0, n - 1, l, r, 0);
}

// A recursive function that constructs Segment
// Tree for array[ss..se]. si is index of
// current node in segment tree st
int constructSTUtil(int arr[], int ss, int se,
                    int* st, int si)
{
    // If there is one element in array, store
    // it in current node of segment tree and return
    if (ss == se)
    {
        st[si] = arr[ss];
        return arr[ss];
    }

    // If there are more than one elements, then
    // recur for left and right subtrees and
    // store the max of values in this node
    int mid = getMid(ss, se);

    st[si] = max(constructSTUtil(arr, ss, mid, st,
                                 si * 2 + 1),
                 constructSTUtil(arr, mid + 1, se,
                                 st, si * 2 + 2));

    return st[si];
}

/* Function to construct segment tree from given array.
   This function allocates memory for segment tree.*/
int* constructST(int arr[], int n)
{
    // Height of segment tree
    int x = (int)(ceil(log2(n)));

    // Maximum size of segment tree
    int max_size = 2 * (int)pow(2, x) - 1;

    // Allocate memory
    int* st = new int[max_size];

    // Fill the allocated memory st
    constructSTUtil(arr, 0, n - 1, st, 0);

    // Return the constructed segment tree
    return st;
}

int main()
{
    int p,k;
    cin>>p>>k;
    int v[p];
    int mm=0;
    fi(i,0,p) cin>>v[i],mm=max(mm,v[i]);
    int arr[mm+1+k];
    fi(i,0,mm+1+k) arr[i]=0;
    int n = sizeof(arr) / sizeof(arr[0]);
    int* st = constructST(arr, n);
    int dp[p];
    fi(i,0,p) dp[i]=1;
    dp[0]=1;
    updateValue(arr, st, 0, n - 1, v[0], 1, 0);
    vi vis(mm+1);
    vis[v[0]]=1;
    fi(i,1,p)
    {
        int q;
        if(vis[v[i]]) q=getMax(st, n, max(0,v[i]-k), v[i]+k);
        else
        {
            q=getMax(st, n, max(0,v[i]-k), max(0,v[i]-1));
            q=max(q,getMax(st, n, v[i]+1, v[i]+k));
        }
        vis[v[i]]=1;
        dp[i]=max(dp[i],q+1);
      //  cout<<v[i]<<" "<<q<<" "<<dp[i]<<"\n";
        updateValue(arr, st, 0, n - 1, v[i], dp[i], 0);
    }
    int mx=0;
    fi(i,0,p) mx=max(mx,dp[i]);
    cout<<mx;
}









Measured memory_bytes: 17516