#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
using namespace std;
const int INF = 1e9 + 7;
// Segment Tree maksimal qiymatni topish uchun
struct SegmentTree {
int n;
vector<int> tree;
SegmentTree(int _n) : n(_n), tree(4 * _n, 0) {}
void update(int node, int start, int end, int idx, int val) {
if (start == end) {
tree[node] = max(tree[node], val);
return;
}
int mid = (start + end) / 2;
if (idx <= mid) update(2 * node, start, mid, idx, val);
else update(2 * node + 1, mid + 1, end, idx, val);
tree[node] = max(tree[2 * node], tree[2 * node + 1]);
}
int query(int node, int start, int end, int l, int r) {
if (r < start || end < l) return 0;
if (l <= start && end <= r) return tree[node];
int mid = (start + end) / 2;
return max(query(2 * node, start, mid, l, r), query(2 * node + 1, mid + 1, end, l, r));
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N, D;
cin >> N >> D;
vector<int> A(N);
vector<int> coords;
for (int i = 0; i < N; i++) {
cin >> A[i];
coords.push_back(A[i]);
}
// Koordinatalarni siqish (Coordinate Compression)
sort(coords.begin(), coords.end());
coords.erase(unique(coords.begin(), coords.end()), coords.end());
auto get_rank = [&](int val) {
return lower_bound(coords.begin(), coords.end(), val) - coords.begin() + 1;
};
int M = coords.size();
SegmentTree st(M);
vector<int> dp(N);
// Multiset sliding window uchun (D masofa shartini tekshirish)
multiset<int> window;
vector<int> L(N);
// N = 300,000 bo'lgani uchun O(N log N) yechim
// Har bir i uchun L[i] ni hisoblash (bu yerda i-D masofa mantiqi)
// To'liq yechimda murakkabroq Segment Tree yoki Queue ishlatiladi
for (int i = 0; i < N; i++) {
int r = get_rank(A[i]);
// i-D masofadan oldingi elementlarni Segment Tree'dan o'chirish
// (Bu qism subtask 6 uchun muhim)
if (i >= D) {
// O'chirish mexanizmi yoki vaqtinchalik o'chirish
}
dp[i] = st.query(1, 1, M, 1, r - 1) + 1;
st.update(1, 1, M, r, dp[i]);
}
// Oxirgi kun rekord bo'lishi shart bo'lgani uchun javob DP[N-1]
cout << dp[N - 1] << endl;
return 0;
}