#include<bits/stdc++.h>
using namespace std;
#define rep(i,n) for(int i = 0; i < (n); i++)




//segment-tree
class segment_tree{
    private:
        vector<int> value; // ノードの値を持つ配列
    public:
        int N;             // 葉の数
        int bilower(int x){
            int ans = 1;
            while(ans < x) ans <<= 1;
            return ans;
        }
        segment_tree(int nodenum, int maxval){
            N = bilower(nodenum);
            value = vector<int> (2*N,maxval);
        }
        void update(int i, int x){
            // i 番目の葉の値を x に変える
            i += N - 1; // i 番目の葉のノード番号
            value[i] = x;
            while (i > 0) {
                i = (i - 1) / 2; // ノード i の親ノードの番号に変える
                value[i] = min(value[i * 2 + 1], value[i * 2 + 2]); // 左右の子の min を計算しなおす
            }
        }
        int query(int a, int b, int k, int l, int r){
            // [a, b)の区間に対するクエリについて
            // ノード k （区間 [l, r) 担当）が答える
            if (r <= a || b <= l) return 200001; // 区間が被らない場合は 200001 を返す
            if (a <= l && r <= b) return value[k]; // ノード k の担当範囲がクエリ区間 [a, b)             
            else{ //に完全に含まれる
                int r1 = query(a, b, 2 * k + 1, l, (l + r) / 2); // 左の子に値を聞く
                int r2 = query(a, b, 2 * k + 2, (l + r) / 2, r); // 右の子に値を聞く
                return min(r1, r2); // 左右の子の値の min を取る
            }
        }
};


//unionfind
//init: union_find name(size)

class union_find{
private:
    //根にはグループの要素数に―1をかけたもの、それ以外には根の値
    //初期値は-1
    vector<int> uni;
public:
    //Constructer
    //uniを必要なサイズで初期化する、初期値は―1
    union_find(int unisize) : uni(unisize,-1){}

    //引数aの根を求める、なければaを根として返す
    int root(int a){
        if(uni[a] < 0) return a;
        return uni[a] = root(uni[a]);  
    }

    //頂点aとbを繋ぐ関数unite
    //戻り値：
    //  元々同じグループであればfalse
    //  連結に成功すればtrue
    bool unite(int a, int b){
        //a, bにそれぞれが属するグループの根を入れる
        //uni[a], uni[b]がa, bがそれぞれが属するグループのサイズになる
        a = root(a);
        b = root(b);
        if(a == b) return false;
        if(uni[a] > uni[b]) swap(a,b); //bの方を大きいものにする
        uni[a] += uni[b];
        uni[b] = a; //大きい方のグループに属するものの親を小さいものの根にする(rootが高速で動くようになる)
        return true;
    }
    //頂点aとbが同じグループかを調べる
    bool isConnected(int a, int b){
        return root(a) == root(b);
    }
    //頂点aを含むグループの頂点数を調べる
    int unisize(int a){
        return -uni[root(a)];
    }
};

int main(){
    int n,k; cin >> n >> k;
    vector<int> p(n); rep(i,n) cin >> p[i];
    union_find uf(n+1);
    vector<int> sum(n+1);
    segment_tree maxsg(n,200001);
    segment_tree minsg(n,200001);

    //累積和をとって昇順かを判定
    //接続先はnとして、ただし最後の集計でnを調べない
    rep(i,n-1) sum[i+1] = (p[i] > p[i+1]);
    rep(i,n) sum[i+1] += sum[i];
    rep(i,n-k+1) if(sum[i] == sum[i+k-1]) uf.unite(i,n);
    
    //RMQ
    for(int i = 0; i < n; i++){
        minsg.update(i,p[i]);
        maxsg.update(i,-p[i]);
    }
    for(int i = 1; i < n-k+1; i++){
        if(maxsg.query(i, i+k, 0, 0, maxsg.N) == -p[i+k-1] && minsg.query(i-1, i+k-1, 0, 0, minsg.N) == p[i-1]){
            uf.unite(i,i-1);
        }
    }

    //answer
    int ans = 0;
    rep(i,n-k+1) if(uf.root(i) == i) ans++; //nまでは調べてはいけない
    cout << ans << endl;
}

Measured memory_bytes: 6656