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.Collections;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using static MyIO;


public class B
{
	public static void Main() => (new Solver()).Solve();
}


public class Solver
{
	public void Solve()
	{
		int N = GetInt();
		int K = GetInt();
		int[] P = GetInts(N);

		int V = N - K + 1;
		var uf = new UnionFind(V);
		int cnt = 1;
		int sorted = -1;
		for(int i = 1; i < N; i++)
		{
			if(P[i] > P[i - 1])
			{
				cnt++;
			}
			else
			{
				cnt = 1;
			}

			if(cnt >= K)
			{
				if(sorted == -1)
				{
					sorted = i - K + 1;
				}
				else if(!uf.IsSame(sorted, i - K + 1))
					uf.Merge(sorted, i - K + 1);
			}
		}

		var sMin = new Deque<int>(N);
		for(int i = 0; i < K; i++)
			pushMin(sMin, P, i);
		
		var sMax = new Deque<int>(N);
		for(int i = 0; i < K; i++)
			pushMax(sMax, P, i);

		for(int i = 0; i < N - K; i++)
		{
			pushMin(sMin, P, i + K);
			pushMax(sMax, P, i + K);

			int argMin = sMin.PeekFront();
			int min = P[argMin];
			if(argMin == i)
				sMin.PopFront();

			int argMax = sMax.PeekFront();
			int max = P[argMax];
			if(argMax == i)
				sMax.PopFront();

			if((P[i] == min) && (P[i + K] == max))
			{
				if(!uf.IsSame(i, i + 1))
					uf.Merge(i, i + 1);
			}
		}

		int ans = 0;
		var set = new HashSet<int>();
		for(int i = 0; i < V; i++)
		{
			int r = uf.Root(i);
			if(!set.Contains(r))
			{
				set.Add(r);
				ans++;
			}
		}
		Console.WriteLine(ans);
	}

	private void pushMin(Deque<int> sMin, int[] P, int i)
	{
		while(sMin.Count > 0 && P[sMin.PeekBack()] >= P[i])
			sMin.PopBack();

		sMin.PushBack(i);
	}

	private void pushMax(Deque<int> sMax, int[] P, int i)
	{
		while(sMax.Count > 0 && P[sMax.PeekBack()] <= P[i])
			sMax.PopBack();

		sMax.PushBack(i);
	}
}

public class Deque<T>
{
	private int N; 
	private T[] buf;
	private int front;
	private int back;

	public int Count => (front <= back) ? back - front : N - front + back;

	public Deque(int n)
	{
		N = n;
		buf = new T[N];
		front = 0;
		back = 0;
	}

	public void PushBack(T data)
	{
		if(Count == N)
			throw new Exception();

		buf[back] = data;
		back = inc(back);
	}

	public T PeekBack() => buf[dec(back)];

	public T PopBack()
	{
		if(Count == 0)
			throw new Exception();

		back = dec(back);
		return buf[back];
	}
	
	public void PushFront(T data)
	{
		if(Count == N)
			throw new Exception();

		front = dec(front);
		buf[front] = data;
	}

	public T PeekFront() => buf[front];

	public T PopFront()
	{
		if(Count == 0)
			throw new Exception();

		T res = buf[front];
		front = inc(front);
		return res;
	}

	private int inc(int x) => (x == N - 1) ? 0 : x + 1;
	private int dec(int x) => (x == 0) ? N - 1 : x - 1;
}

public class UnionFind
{
	private int[] par = null;
	private int[] rank = null;
	private int[] ccSize = null;
	
	public UnionFind(int n)
	{
		par = new int[n];
		rank = new int[n];
		ccSize = new int[n];
		for(int i = 0; i < n; i++)
		{
			par[i] = i;
			rank[i] = 0;
			ccSize[i] = 1;
		}
	}

	public bool IsSame(int x, int y)
	{
		return (Root(x) == Root(y));
	}

	public int Root(int x)
	{
		if(par[x] == x)
			return x;

		int r = Root(par[x]);
		par[x] = r;
		return r;
	}
	
	public bool Merge(int x, int y)
	{
		int rx = Root(x);
		int ry = Root(y);
		if(rx == ry)
			return false;
		
		if(rank[rx] < rank[ry])
		{
			int tmp = rx;
			rx = ry;
			ry = tmp;
		}
		else if(rank[rx] == rank[ry])
			rank[rx]++;

		par[ry] = rx;
		ccSize[rx] = ccSize[rx] + ccSize[ry];
		return true;
	}

	public int Size(int x)
	{
		return ccSize[Root(x)];
	}
}

public static class MyIO
{
	private static string[] args = null;
	private static int num = -1;
	private static int used = -1;

	private static string getArg()
	{
		if(used == num)
		{
			args = Console.ReadLine().Split(' ');
			num = args.Length;
			used = 0;
		}
		return args[used++];
	}

	public static int GetInt() => int.Parse(getArg());
	public static long GetLong() => long.Parse(getArg());
	public static double GetDouble() => double.Parse(getArg());
	public static string GetString() => getArg();
	public static char GetChar() => getArg()[0];
	public static int[] GetInts(int N) => Enumerable.Range(0, N).Select(_ => GetInt()).ToArray();
	public static long[] GetLongs(int N) => Enumerable.Range(0, N).Select(_ => GetLong()).ToArray();
	public static double[] GetDoubles(int N) => Enumerable.Range(0, N).Select(_ => GetDouble()).ToArray();
	public static string[] GetStrings(int N) => Enumerable.Range(0, N).Select(_ => GetString()).ToArray();
}