AtCoder Regular Contest 102 - Revenge of BBuBBBlesort!

You are given a permutation of 1,2,...,N: p_1,p_2,...,p_N. Determine if the state where p_i=i for every i can be reached by performing the following operation any number of times:
 - Choose three elements p_{i-1},p_{i},p_{i+1} (2\leq i\leq N-1) such that p_{i-1}>p_{i}>p_{i+1} and reverse the order of these three.

-----Constraints-----
 - 3 \leq N \leq 3 × 10^5
 - p_1,p_2,...,p_N is a permutation of 1,2,...,N.

-----Input-----
Input is given from Standard Input in the following format:
N
p_1
:
p_N

-----Output-----
If the state where p_i=i for every i can be reached by performing the operation, print Yes; otherwise, print No.

-----Sample Input-----
5
5
2
1
4
3

-----Sample Output-----
Yes

The state where p_i=i for every i can be reached as follows:
 - Reverse the order of p_1,p_2,p_3. The sequence p becomes 1,2,5,4,3.
 - Reverse the order of p_3,p_4,p_5. The sequence p becomes 1,2,3,4,5.

Source: atcoder | Difficulty: VERY_HARD


Solutions:
import sys
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
readlines = sys.stdin.buffer.readlines
N = int(readline())
P = [0] + list(map(int, read().split()))
intervals = []
left = 0
right = -1
for (i, p) in enumerate(P):
	if right < p:
		right = p
	if i == right:
		intervals.append((left, right))
		left = i + 1
		right = -1

def check(L, R):
	if L == R:
		return True
	to_left = []
	fixed = []
	to_right = []
	for (i, p) in enumerate(P[L:R + 1], L):
		if i > p:
			to_left.append(p)
		elif i == p:
			fixed.append(p)
		else:
			to_right.append(p)
	if fixed != list(range(L + 1, R + 1, 2)):
		return False
	if any((x > y for (x, y) in zip(to_left, to_left[1:]))):
		return False
	if any((x > y for (x, y) in zip(to_right, to_right[1:]))):
		return False
	return True
answer = 'Yes' if all((check(L, R) for (L, R) in intervals)) else 'No'
print(answer)


def Split(a):
	no = []
	for (i, x) in a:
		if no:
			is_ok = i == x
			la_ok = no[-1][0] == no[-1][1]
			if is_ok == la_ok:
				yield no
				no = []
		no.append((i, x))
	yield no
n = int(input())
p = list(enumerate((int(input()) for i in range(n)), 1))
for sq in Split(p):
	tl = tr = 0
	for (np, goal) in sq:
		if goal > np:
			if goal < tr or goal > sq[-1][0]:
				print('No')
				exit(0)
			tr = goal
		elif goal < np:
			if goal < tl or goal < sq[0][0]:
				print('No')
				exit(0)
			tl = goal
print('Yes')


import sys

def solve(ppp):
	section_start = -1
	moved_left_max = 0
	moved_right_max = 0
	prev = True
	for (i, p) in enumerate(ppp, start=1):
		if i == p:
			if prev:
				moved_left_max = 0
				moved_right_max = 0
				section_start = -1
			prev = True
		else:
			if not prev:
				if moved_left_max > i - 1:
					return False
				moved_left_max = 0
				moved_right_max = 0
				section_start = i
			if section_start == -1:
				section_start = i
			if i > p:
				if section_start > p:
					return False
				if moved_right_max > p:
					return False
				moved_right_max = p
			else:
				if moved_left_max > p:
					return False
				moved_left_max = p
			prev = False
	return True
(n, *ppp) = list(map(int, sys.stdin))
print('Yes' if solve(ppp) else 'No')


def Split(a):
	no = []
	for (i, x) in a:
		if no and (i == x) == (no[-1][0] == no[-1][1]):
			yield no
			no = []
		no.append((i, x))
	yield no
for sq in Split(((i + 1, int(input())) for i in range(int(input())))):
	tb = [0, 0]
	for (np, goal) in sq:
		if goal != np:
			if goal < tb[np < goal] or goal > sq[-1][0] or goal < sq[0][0]:
				print('No')
				return
			tb[np < goal] = goal
print('Yes')