unittest
{
	assert( [ "10 3", "1", "5", "4", "3", "8", "6", "9", "7", "2", "4" ].solve == 7 );
}



import std.algorithm;
import std.conv;
import std.format;
import std.range;
import std.stdio;

void main()
{
	stdin.byLineCopy.solve.writeln;
}

auto solve( Range )( Range input )
if( isInputRange!Range && is( ElementType!Range == string ) )
{
	auto n = 0L;
	auto k = 0L;
	input.front.formattedRead!"%s %s"( n, k );
	auto as = new long[ n ];
	foreach( ref a; as )
	{
		input.popFront;
		a = input.front.to!( long );
	}
	
	auto st = SegmentTree!( long, 0L, max, max )( 300001 );
	foreach( a; as )
	{
		st.update( a, 1 + st.query( max( 0, a - k ), min( a + k + 1, st.length ) ) );
	}
	return st.query( 0L, st.length );
}

// セグメント木
struct SegmentTree( T, T I, alias op_v, alias op_m )
{
	size_t n;
	T[] vs;
	
	this( size_t n )
	{
		this.n = n;
		this.vs = new T[ this.n << 1 ];
		static if( I != T.init ) this.vs[] = I;
	}
	
	this( T[] vs )
	{
		this( vs.length );
		this.vs[ this.n .. this.n + vs.length ] = vs[];
		foreach_reverse( p; 1L .. this.n )
		{
			this.vs[ p ] = op_v( this.vs[ p << 1 ], this.vs[ p << 1 | 1 ] );
		}
	}
	
	void update( size_t i, T e )
	{
		auto p = this.n + i;
		this.vs[ p ] = op_m( this.vs[ p ], e );
		for( p >>= 1; 0 < p; p >>= 1 )
		{
			this.vs[ p ] = op_v( this.vs[ p << 1 ], this.vs[ p << 1 | 1 ] );
		}
	}
	
	auto query( size_t i )
	{
		return this.vs[ this.n + i ];
	}
	
	auto query( size_t l, size_t r )
	{
		auto lt = I;
		auto rt = I;
		for( auto lp = this.n + l, rp = this.n + r; lp < rp; lp >>= 1, rp >>= 1 )
		{
			if( lp & 1 )
			{
				lt = op_v( lt, this.vs[ lp ] );
				lp++;
			}
			if( rp & 1 )
			{
				rp--;
				rt = op_v( this.vs[ rp ], rt );
			}
		}
		return op_v( lt, rt );
	}
	
	auto length()
	{
		return this.n;
	}
	
	auto toString()
	{
		return format( "ST(%s)", this.vs[ this.n .. $ ] );
	}
}
