#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <queue>
#include <string>
#include <map>
#include <set>
#include <stack>
#include <tuple>
#include <deque>
#include <numeric>
#include <bitset>
#include <iomanip>
#include <cassert>
#include <chrono>
#include <random>
#include <limits>
#include <iterator>
#include <functional>
#include <sstream>
#include <complex>
using namespace std;

using ll = long long;
using ull = uint64_t;
using P = pair<int, int>;
constexpr double EPS = 1e-9;
constexpr int INF = 1001001001;
constexpr int mod = 1000000007;
// constexpr int mod = 998244353;

template<class T>
inline bool chmax(T& x, T y){
    if(x < y){
        x = y;
        return true;
    }
    return false;
}
template<class T>
inline bool chmin(T& x, T y){
    if(x > y){
        x = y;
        return true;
    }
    return false;
}

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[k << 1], seg[k << 1 | 1]);
        }
    }

    void update(int k, const Monoid &x){
        k += sz;
        seg[k] = x;
        while(k >>= 1){
            seg[k] = f(seg[k << 1], seg[k << 1 | 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];
    }
};

struct UnionFind{
    int sz;     // vertex number
    vector<int> par;
    vector<int> rank;

    UnionFind(int n) : sz(n) {
        par.resize(sz);
        rank.assign(sz, 0);
        for(int i = 0; i < sz; ++i){
            par[i] = i;
        }
    }

    int find(int x){
        if(par[x] == x) return x;
        else    return par[x] = find(par[x]);
    }

    bool same(int x, int y){
        return find(x) == find(y);
    }

    void unite(int x, int y){
        x = find(x), y = find(y);
        if(x == y)  return;
        if(rank[x] < rank[y])   par[x] = y;
        else{
            par[y] = x;
            if(rank[x] == rank[y])  ++rank[x];
        }
    }
};

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, k;
    cin >> n >> k;
    vector<int> p(n);
    SegmentTree<int> MinSeg(n, [](int a, int b){return min(a, b);}, INF);
    SegmentTree<int> MaxSeg(n, [](int a, int b){return max(a, b);}, -1);
    for(int i = 0; i < n; ++i){
        cin >> p[i];
        MinSeg.set(i, p[i]);
        MaxSeg.set(i, p[i]);
    }
    MinSeg.build();
    MaxSeg.build();
    UnionFind uf(n);
    vector<int> Ascending;
    int c = 0;
    for(int i = 1; i < n; ++i){
        if(i >= k){
            if(c == k - 1)  Ascending.emplace_back(i - k);
            if(p[i - k] < p[i - k + 1]) --c;
        }
        if(p[i - 1] < p[i]) ++c;
    }
    if(c == k - 1)  Ascending.emplace_back(n - k);
    int sz = Ascending.size();
    if(Ascending.size()){
        int u = Ascending[0];
        for(int i = 1; i < sz; ++i){
            int v = Ascending[i];
            uf.unite(u, v);
        }
    }
    for(int i = 0; i + k < n; ++i){
        int L = MinSeg.query(i, i + k);
        int R = MaxSeg.query(i + 1, i + k + 1);
        if(L == p[i] && R == p[i + k])  uf.unite(i, i + 1);
    }
    set<int> st;
    for(int i = 0; i + k <= n; ++i) st.insert(uf.find(i));
    int ans = st.size();
    cout << ans << endl;
}

Measured memory_bytes: 18868