#include <bits/stdc++.h>

#ifdef __LOCAL
    #define DBG(X) cout << #X << " = " << (X) << endl;
    #define SAY(X) cout << (X) << endl;
#else
    #define DBG(X)
    #define SAY(X)
#endif

#ifdef __LOCAL
    #include <filesystem>
    namespace fs = std::filesystem;
#endif

using namespace std;

using ll = long long int;
using ull = unsigned long long int;
using ld = long double;
using pii = pair<int, int>;
using pll = pair<ll, ll>;

int dx[]={1, 0, -1, 0, 0};
int dy[]={0, 1, 0, -1, 0};
const int INT_INF = (int)(2e9);
const ll  LL_INF = (ll)(2e18);

inline void fast_io() { ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); };
template<typename T, typename S> inline ostream& operator<<(ostream& os, const pair<T, S> p) { cout << "[" << p.first << ";" << p.second << "]"; return os; }
template<typename T> inline ostream& operator<<(ostream& os, const vector<T>& v) { for (auto el : v) cout << el << " "; return os; }
template<typename T> inline vector<T> fetch_vec(int sz) { vector<T> ret(sz); for (auto& elem : ret) cin >> elem; return ret; }

template< typename Monoid >
struct SegmentTree {
  using F = function< Monoid(Monoid, Monoid) >;

  int sz;
  vector< Monoid > seg;

  const F f;
  const Monoid M1;

  SegmentTree(int n, const F f, const Monoid &M1) : f(f), M1(M1) {
    sz = 1;
    while(sz < n) sz <<= 1;
    seg.assign(2 * sz, M1);
  }

  void set(int k, const Monoid &x) {
    seg[k + sz] = x;
  }

  void build() {
    for(int k = sz - 1; k > 0; k--) {
      seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]);
    }
  }

  void update(int k, const Monoid &x) {
    k += sz;
    seg[k] = x;
    while(k >>= 1) {
      seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]);
    }
  }

  Monoid query(int a, int b) {
    Monoid L = M1, R = M1;
    for(a += sz, b += sz; a < b; a >>= 1, b >>= 1) {
      if(a & 1) L = f(L, seg[a++]);
      if(b & 1) R = f(seg[--b], R);
    }
    return f(L, R);
  }

  Monoid operator[](const int &k) const {
    return seg[k + sz];
  }

  template< typename C >
  int find_subtree(int a, const C &check, Monoid &M, bool type) {
    while(a < sz) {
      Monoid nxt = type ? f(seg[2 * a + type], M) : f(M, seg[2 * a + type]);
      if(check(nxt)) a = 2 * a + type;
      else M = nxt, a = 2 * a + 1 - type;
    }
    return a - sz;
  }


  template< typename C >
  int find_first(int a, const C &check) {
    Monoid L = M1;
    if(a <= 0) {
      if(check(f(L, seg[1]))) return find_subtree(1, check, L, false);
      return -1;
    }
    int b = sz;
    for(a += sz, b += sz; a < b; a >>= 1, b >>= 1) {
      if(a & 1) {
        Monoid nxt = f(L, seg[a]);
        if(check(nxt)) return find_subtree(a, check, L, false);
        L = nxt;
        ++a;
      }
    }
    return -1;
  }

  template< typename C >
  int find_last(int b, const C &check) {
    Monoid R = M1;
    if(b >= sz) {
      if(check(f(seg[1], R))) return find_subtree(1, check, R, true);
      return -1;
    }
    int a = sz;
    for(b += sz; a < b; a >>= 1, b >>= 1) {
      if(b & 1) {
        Monoid nxt = f(seg[--b], R);
        if(check(nxt)) return find_subtree(b, check, R, true);
        R = nxt;
      }
    }
    return -1;
  }
};


int N,K;
vector<int> P;

void input(){
    fast_io();
    #ifdef __LOCAL
        fs::path p = __FILE__;
        fs::path input,output;
        input = output = p.parent_path();
        input += string("/input/") + string(p.stem()) + string(".txt");
        output += string("/output/") + string(p.stem()) + string(".txt");
        freopen(input.c_str(), "r", stdin);
        freopen(output.c_str(), "w", stdout);
    #endif
    cin >> N >> K;
    P = fetch_vec<int>(N);
}

int TLEsolve(){
    if(K==1) {cout << 1 << endl; return 0;}
    if(K==N) {cout << 1 << endl; return 0;}
    // 計算量を考慮せずに愚直にやる場合・・・
    map<vector<int>,int> cnt;
    vector<int> A;
    for (int i = 0; i <= N-K; i++)
    {
        A = P;
        sort(A.begin()+i,A.begin()+i+K);
        cnt[A]++;
        A.clear();
    }
    int ans;
    ans = cnt.size();
    cout << ans << endl;
    return ans;
}

map<int,vector<int>> G;
vector<bool> visited;

int dfs(int i){
    // if(visited[i]) return 0;
    visited[i] = true;
    for(auto to:G[i]) {
        if(visited[to]) continue; 
        dfs(to);
        }
    return 0;
}

// RMQ だとO(NlogN)かかる
// スライド最小値だとO(N)
int RMQsolve(){
    if(K==1) {cout << 1 << endl; return 0;}
    if(K==N) {cout << 1 << endl; return 0;}
    // deque<int> A;
    // しゃくとり法的にやる。
    // a1...a'i...a'i+k-1...an-1
    // a1...a'i+1...a'i+k...an-1
    // が同じ列 <==>
    // ai = min(ai,...,ai+k-1) and 
    // ai+k > max(ai,...,ai+k-1)

    // セグ木使えばdequeは要らない。
    // for (int i = 0; i < K; i++)
    // {
    //     A.push_back(P[i]);
    // }

    [&](){
    vector<pii> ZL;
    vector<int> sortedIdx;
    int r=0;
    for (int i = 0; i < N-1; i++)
    {
        if(P[i]<P[i+1]) r++;
        // else if(i==N-1) {r++;ZL.push_back(r);r=0;}
        else {r++;if(r>=K){ZL.push_back({i,r});}r=0;}
    }
    r++;
    if(r>=K) ZL.push_back({N-1,r});
    DBG(ZL)
    for(auto z:ZL) while(z.second>=K) {sortedIdx.push_back(z.first-z.second+1);z.second--;}
    ZL.clear();
    DBG(sortedIdx)
    for(auto i:sortedIdx) G[i]=sortedIdx;
    sortedIdx.clear();
    }();

    [&](){
    SegmentTree< int > segMin(N, [](int a, int b) { return min(a, b); }, N+10);
    SegmentTree< int > segMax(N, [](int a, int b) { return max(a, b); }, 0);
    for (int i = 0; i < N; i++)
    {
        segMin.update(i,P[i]);
        segMax.update(i,P[i]);
    }
    
    // max,minのクエリはセグ木を構築して高速化する。
    int mi = segMin.query(0,K);
    int ma = segMax.query(0,K);
    for (int i = 0; i < N-K; i++)
    {
        int out = P[i];
        int in = P[i+K];
        if(mi==out && ma<in){G[i].push_back(i+1); G[i+1].push_back(i); ma=in; mi=segMin.query(i+1,i+K+1);}
        // else if(mi!=out && ma<in) {ma=in;}
        // else if(mi==out && ma>=in){mi=segMin.query(i+1,i+K+1);}
        // else if(mi!=out && ma>=in && ma==out){mi=min(mi,in);ma=segMax.query(i+1,i+K+1);}
        // else if(mi!=out && ma>=in && ma!=out){mi=min(mi,in);}
        else {ma=segMax.query(i+1,i+K+1); mi=segMin.query(i+1,i+K+1);}
        // seg.query(a,b) : [a,b)に対する操作なのでbは対象外であることに注意
    }
    }();

    int ans=0;
    visited.assign(N,false);
    for (int i = 0; i <= N-K; i++)
    {
        if(visited[i]) continue;
        dfs(i); 
        ans++;
    }
    cout << ans << endl;
    return ans;
}

int solve(){
    if(K==1) {cout << 1 << endl; return 0;}
    if(K==N) {cout << 1 << endl; return 0;}
    // deque<int> A;
    // しゃくとり法的にやる。
    // a1...a'i...a'i+k-1...an-1
    // a1...a'i+1...a'i+k...an-1
    // が同じ列 <==>
    // ai = min(ai,...,ai+k-1) and 
    // ai+k > max(ai,...,ai+k-1)

    // セグ木使えばdequeは要らない。
    // for (int i = 0; i < K; i++)
    // {
    //     A.push_back(P[i]);
    // }

    [&](){
    vector<pii> ZL;
    vector<int> sortedIdx;
    int r=0;
    for (int i = 0; i < N-1; i++)
    {
        if(P[i]<P[i+1]) r++;
        // else if(i==N-1) {r++;ZL.push_back(r);r=0;}
        else {r++;if(r>=K){ZL.push_back({i,r});}r=0;}
    }
    r++;
    if(r>=K) ZL.push_back({N-1,r});
    DBG(ZL)
    for(auto z:ZL) while(z.second>=K) {sortedIdx.push_back(z.first-z.second+1);z.second--;}
    ZL.clear();
    DBG(sortedIdx)
    if(sortedIdx.size()>0){
        int j = sortedIdx[0];
        for(auto &i:sortedIdx) {
            G[i].push_back(j);
            G[j].push_back(i);
            }
        sortedIdx.clear();
    }
    }();

    // スライド最小値
    deque<int> deq;
    vector<int> slideMin(N);
    for (int i = 0; i < N; i++)
    {
        while(!deq.empty() && P[deq.back()] >= P[i]) deq.pop_back();
        deq.push_back(i);
        if(i-K+1>=0){
            slideMin[i-K+1] = P[deq.front()];
            if(deq.front()==i-K+1) deq.pop_front();
        }
    }
    DBG(slideMin)

    deq.clear();
    vector<int> slideMax(N);
    for (int i = 0; i < N; i++)
    {
        while(!deq.empty() && P[deq.back()] <= P[i]) deq.pop_back();
        deq.push_back(i);
        if(i-K+1>=0){
            slideMax[i-K+1] = P[deq.front()];
            if(deq.front()==i-K+1) deq.pop_front();
        }
    }
    DBG(slideMax)
    deq.clear();

    int mi = slideMin[0];
    int ma = slideMax[0];
    int in, out;
    for (int i = 0; i < N-K; i++)
    {
        out = P[i];
        in = P[i+K];
        if(mi==out && ma<in){G[i].push_back(i+1); G[i+1].push_back(i);}
        ma=slideMax[i+1];
        mi=slideMin[i+1];
    }

    int ans=0;
    visited.assign(N,false);
    for (int i = 0; i <= N-K; i++)
    {
        if(visited[i]) continue;
        dfs(i); 
        ans++;
    }
    cout << ans << endl;
    return ans;
}

int main()
{
    input();
    solve();
    return 0;
}


Measured memory_bytes: 40932