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;
        DisjointSparseTable<Incr> isIncr = new DisjointSparseTable<Incr>(p.Select(x => new Incr() { L = x, R = x, Valid = true }).ToArray(), Incr.Merge);
        DisjointSparseTable<int> rmin = new DisjointSparseTable<int>(p, Min);
        DisjointSparseTable<int> rmax = new DisjointSparseTable<int>(p, Max);
        long incrCount = isIncr.Query(0, k - 1).Valid ? 1 : 0;
        for (int i = 1; i <= n - k; i++)
        {
            if (rmax.Query(i, i + k - 1) != p[i + k - 1] || rmin.Query(i - 1, i + k - 2) != p[i - 1])
            {
                if (isIncr.Query(i, i + k - 1).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 DisjointSparseTable<T>
{
    public readonly int Size;
    readonly int Height;
    readonly T[] Table;
    readonly Func<T, T, T> Merge;

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public DisjointSparseTable(T[] data, Func<T, T, T> merge)
    {
        Size = data.Length;
        Height = GetMSB(Size) + 1;
        Table = new T[Size * Height];
        Merge = merge;
        data.CopyTo(Table, 0);
        for (int layer = 1; layer < Height; layer++)
        {
            int layerOffset = layer * Size;
            int block = 0;
            int i;
            int bound;
            for (; block + 2 <= Size >> layer; block += 2)
            {
                i = layerOffset + ((block | 1) << layer) - 1; Table[i] = Table[i - layerOffset]; i--;
                bound = layerOffset + (block << layer);
                for (; i >= bound; i--) Table[i] = Merge(Table[i - layerOffset], Table[i + 1]);

                i = layerOffset + ((block | 1) << layer); Table[i] = Table[i - layerOffset]; i++;
                bound = layerOffset + ((block + 2) << layer);
                for (; i < bound; i++) Table[i] = Merge(Table[i - 1], Table[i - layerOffset]);
            }
            if (Size <= ((block | 1) << layer)) continue;
            {
                i = layerOffset + Min((block | 1) << layer, Size) - 1; Table[i] = Table[i - layerOffset]; i--;
                bound = layerOffset + (block << layer);
                for (; i >= bound; i--) Table[i] = Merge(Table[i - layerOffset], Table[i + 1]);

                i = layerOffset + ((block | 1) << layer); Table[i] = Table[i - layerOffset]; i++;
                bound = layerOffset + Size;
                for (; i < bound; i++) Table[i] = Merge(Table[i - 1], Table[i - layerOffset]);
            }
        }
    }

    public T Query(int l, int r)
    {
        if (l == r) return Table[l];
        var layer = GetMSB(l ^ r);
        return Merge(Table[l + layer * Size], Table[r + layer * Size]);
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    static int GetMSB(int n)
    {
        int res = 0;
        if (0 != (n >> (res | 16))) res |= 16;
        if (0 != (n >> (res | 8))) res |= 8;
        if (0 != (n >> (res | 4))) res |= 4;
        if (0 != (n >> (res | 2))) res |= 2;
        if (0 != (n >> (res | 1))) res |= 1;
        return res;
    }
}