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# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
using static System.Math;
using MethodImplOptions = System.Runtime.CompilerServices.MethodImplOptions;
using MethodImplAttribute = System.Runtime.CompilerServices.MethodImplAttribute;

public static class P
{
    static int h;
    static int w;
    static int a;
    static int b;
    public static void Main()
    {
        var nk = Console.ReadLine().Split().Select(int.Parse).ToArray();
        var n = nk[0];
        var k = nk[1];
        var p = Console.ReadLine().Split().Select(int.Parse).ToArray();
        long res = 1;
        AggregationQueue<Incr> isIncr = new AggregationQueue<Incr>(Incr.Merge);
        MonoidAggregationQueue<int> rmin = new MonoidAggregationQueue<int>(Min, int.MaxValue);
        MonoidAggregationQueue<int> rmax = new MonoidAggregationQueue<int>(Max, int.MinValue);

        for (int i = 0; i < k; i++)
        {
            isIncr.Push(new Incr() { L = p[i], R = p[i], Valid = true });
            rmin.Push(p[i]);
            rmax.Push(p[i]);
        }
        
        long incrCount = isIncr.Value.Valid ? 1 : 0;
        for (int i = k; i < n; i++)
        {
            var min = rmin.Value;
            
            isIncr.Push(new Incr() { L = p[i], R = p[i], Valid = true });
            isIncr.Pop();
            rmin.Push(p[i]);
            rmin.Pop();
            rmax.Push(p[i]);
            rmax.Pop();

            if (rmax.Value != p[i] || min != p[i - k])
            {
                if (isIncr.Value.Valid) incrCount++;
                res++;
            }
        }

        Console.WriteLine(res - (incrCount <= 1 ? 0 : incrCount - 1));
    }
}

struct Incr
{
    public bool Valid;
    public int L;
    public int R;
    public static Incr Merge(Incr a, Incr b) => a.Valid && b.Valid && a.R < b.L ? new Incr() { L = a.L, R = b.R, Valid = true } : new Incr { Valid = false };
}

class AggregationQueue<T>
{
    public int Count { get; private set; }
    public T Value
    {
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        get
        {
            return
                TailValueStack.Count == 0 ? FrontValue :
                FrontIsEmpty ? TailValueStack.Peek() :
                Merge(TailValueStack.Peek(), FrontValue);
        }
    }

    bool FrontIsEmpty = true;
    T FrontValue;
    Stack<T> Fronts = new Stack<T>();
    Stack<T> TailValueStack = new Stack<T>();

    Func<T, T, T> Merge;

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public AggregationQueue(Func<T, T, T> merge)
    {
        Merge = merge;
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public void Pop()
    {
        ValidateNotEmpty();
        if (TailValueStack.Count == 0) Move();
        TailValueStack.Pop();
        Count--;
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public void Push(T item)
    {
        Fronts.Push(item);
        Count++;
        FrontValue = FrontIsEmpty ? item : Merge(FrontValue, item);
        FrontIsEmpty = false;
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private void Move()
    {
        TailValueStack.Push(Fronts.Pop());
        while (0 < Fronts.Count)
            TailValueStack.Push(Merge(Fronts.Pop(), TailValueStack.Peek()));
        FrontIsEmpty = true;
    }

    private void ValidateNotEmpty() { if (Count == 0) throw new Exception(); }
}

class MonoidAggregationQueue<T>
{
    public int Count { get; private set; }
    public T Value { get { return Merge(TailValueStack.Peek(), FrontValue); } }

    T FrontValue;
    Stack<T> Fronts = new Stack<T>();
    Stack<T> TailValueStack = new Stack<T>();

    Func<T, T, T> Merge;
    T Identity;
    
    public MonoidAggregationQueue(Func<T, T, T> merge, T identity)
    {
        Merge = merge;
        Identity = identity;
        TailValueStack.Push(identity);
    }

    public void Pop()
    {
        ValidateNotEmpty();
        if (TailValueStack.Count == 1) Move();
        TailValueStack.Pop();
        Count--;
    }

    public void Push(T item)
    {
        Fronts.Push(item);
        Count++;
        FrontValue = Merge(FrontValue, item);
    }

    private void Move()
    {
        TailValueStack.Push(Fronts.Pop());
        while (0 < Fronts.Count)
            TailValueStack.Push(Merge(Fronts.Pop(), TailValueStack.Peek()));
        FrontValue = Identity;
    }

    private void ValidateNotEmpty() { if (Count == 0) throw new Exception(); }
}