Problem:
Score : 700 points

Problem Statement

Snuke has a permutation (P_0,P_1,\cdots,P_{N-1}) of (0,1,\cdots,N-1).

Now, he will perform the following operation exactly once:

Choose K consecutive elements in P and sort them in ascending order.

Find the number of permutations that can be produced as P after the operation.

Constraints

2 \leq N \leq 200000

2 \leq K \leq N

0 \leq P_i \leq N-1

P_0,P_1,\cdots,P_{N-1} are all different.

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N K
P_0 P_1 \cdots P_{N-1}

Output

Print the number of permutations that can be produced as P after the operation.

Sample Input 1

5 3
0 2 1 4 3

Sample Output 1

2

Two permutations can be produced as P after the operation: (0,1,2,4,3) and (0,2,1,3,4).

Sample Input 2

4 4
0 1 2 3

Sample Output 2

1

Sample Input 3

10 4
2 0 1 3 7 5 4 6 8 9

Sample Output 3

6

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<string>
#include<cstring>
#include<climits>
#include<algorithm>
#include<vector>
#include<cmath>
#include<map>
#include<set>
#include<stack>
#include<queue>
#include<deque>
#include<tuple>
#include<list>
#include<unordered_map>
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
#define vii vector<int>
#define vll vector<ll>
#define lb lower_bound
#define pb push_back
#define mp make_pair
#define rep(i,n) for(ll i=0;i<n;i++)
#define rep2(i,a,b) for(ll i=a;i<b;i++)
#define repr(i,n) for(ll i=n-1;i>=0;i--)
#define all(x) x.begin(),x.end()
#define int ll
using namespace std;
const int INF (1 << 30);
const ll LLINF (1LL << 55LL);
const int MOD = 1000000007;
const int MAX = 510000;

struct UnionFind {
    vector<int> par;
        
    UnionFind(int n) : par(n, -1) { }
    void init(int n) { par.assign(n, -1); }
    
    int find(int x) {
        if (par[x] < 0) return x;
        else return par[x] = find(par[x]);
    }
    
    bool same(int x, int y) {
        return find(x) == find(y);
    }
    
    bool unite(int x, int y) {
        x = find(x); y = find(y);
        if (x == y) return false;
        if (par[x] > par[y]) swap(x, y);
        par[x] += par[y];
        par[y] = x;
        return true;
    }
    
    int size(int x) {
        return -par[find(x)];
    }

    void print(int x){
        rep(i,x){
            cout<<par[i]<<endl;
        }
        return ;
    }
};

struct SegmentTree{
    static const int MAX_N = 1<<18;
    int n,dat[2 * MAX_N -1];
    SegmentTree(int n_){
        n=1;
        while(n<n_) n*= 2;
        for(int i=0;i<2*n-1;i++) dat[i] = INT_MAX;
    }
    void update(int k,int a){
        k += n-1;
        dat[k]=a;
        while(k>0){
            k=(k-1)/2;
            dat[k]=min(dat[k*2+1],dat[k*2+2]);
        }
    }
    int query(int a,int b,int k,int l,int r){
        if(r<=a || b<=l) return INT_MAX;
        if(a<=l && r<=b) return dat[k];
        else{
            int vl = query(a,b,k*2+1,l,(l+r)/2);
            int vr= query(a,b,k*2+2,(l+r)/2,r);
            return min(vr,vl);
        }
    }
    int query(int a,int b){
        return query(a,b,0,0,n);
    }
};

struct SegmentTree1{
    static const int MAX_N = 1<<18;
    int n,dat[2 * MAX_N -1];
    SegmentTree1(int n_){
        n=1;
        while(n<n_) n*= 2;
        for(int i=0;i<2*n-1;i++) dat[i] = -INT_MAX;
    }
    void update(int k,int a){
        k += n-1;
        dat[k]=a;
        while(k>0){
            k=(k-1)/2;
            dat[k]=max(dat[k*2+1],dat[k*2+2]);
        }
    }
    int query(int a,int b,int k,int l,int r){
        if(r<=a || b<=l) return -INT_MAX;
        if(a<=l && r<=b) return dat[k];
        else{
            int vl = query(a,b,k*2+1,l,(l+r)/2);
            int vr= query(a,b,k*2+2,(l+r)/2,r);
            return max(vr,vl);
        }
    }
    int query(int a,int b){
        return query(a,b,0,0,n);
    }
};

signed main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(15);
    ll n,p[200010],k,a[200010];
    set<ll> st;
    pair<ll,ll> pl[200010];
    cin>>n>>k;
    SegmentTree sg(n);
    SegmentTree1 sg1(n);
    UnionFind uf(n);
    rep(i,n){
        cin>>p[i];
        sg.update(i,p[i]);
        sg1.update(i,p[i]);
    }
    for(ll i=1;i<n-k+1;i++){
        pl[i]=pll(sg.query(i,i+k-1),sg1.query(i,i+k-1));
    }
    ll cnt=1,ans=0,S;
    a[0]=1;
    for(ll i=1;i<n;i++){
        if(p[i-1]<p[i]) cnt++;
        else cnt=1;
        a[i]=cnt;
        if(a[i]>=k) st.insert(i-k+1);
    }
    if(st.size()>0){
        auto itr=st.begin();
        S=*itr;
        for(auto i:st){
            uf.unite(S,i);
        }
    }
    rep(i,n-k){
        if(p[i]<pl[i+1].first && pl[i+1].second<p[i+k]){
            uf.unite(i,i+1);
        }
    }
    rep(i,n-k+1){
        if(i==uf.find(i)){
            ans++;
        }
    }
    cout<<ans<<endl;
    return 0;
}