Problem:
F: 紙の折りたたみ / Folding Paper
問題文
高さ $H$ マス、幅 $W$ マスの格子状に区切られた長方形の紙がある。
$0$ から数えて上から $i$ 行目、左から $j$ 列目のマスには整数 $i \times W+j$ が書かれている。 $H=2, W=3$ の例を下の図に示す。
AOR イカちゃんは、この紙に対して次のような操作を順に行った。
$1$ マス分の面積になるまでマスの区切り線に沿って繰り返し折る。この時の折る線や山谷、順番などは任意である。紙を破らない任意の折り方ができる。
$4$ 辺を切り落として $H \times W$ 枚の紙に分割する。
上から順にめくっていき、書かれていた整数を並べた数列 $S$ を作る。
例えば、下の図のように折った後切った場合、$S$ として $4, 3, 0, 5, 2, 1$ が得られる。このように、間に差し込むような折り方も可能である。
あなたは AOR イカちゃんから数列 $S$ を受け取った。
しかし、AOR イカちゃんのことを信用していないので、これが本物か確かめたい。
$S$ と一致するような紙の折り方が存在するなら "YES" を、しないなら "NO" を出力するプログラムを書け。
入力
$H \ W$
$S_0 \cdots S_{HW-1}$
入力の制約
$1 \le H, W \le 500$
$S$ は $0$ から $H \times W - 1$ までの整数を $1$ つずつ含む
出力
"YES" または "NO" を $1$ 行で出力せよ。
サンプル
サンプル入力1
1 4
0 1 2 3
サンプル出力1
YES
サンプル入力2
2 3
4 3 0 5 2 1
サンプル出力2
YES
問題文中の例である。
サンプル入力3
1 4
0 2 1 3
サンプル出力3
NO
サンプル入力4
2 2
0 1 3 2
サンプル出力4
YES
$2$ 回半分に折る。

Submitted solutions:

code_snippet: #include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 1000000007;
const ll INF = mod * mod;
typedef pair<int, int>P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-12;
const ld pi = acos(-1.0);

ll mod_pow(ll x, ll n, ll m = mod) {
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	ll n;
	modint() :n(0) { ; }
	modint(ll m) :n(m) {
		if (n >= mod)n %= mod;
		else if (n < 0)n = (n % mod + mod) % mod;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }

const int max_n = 1 << 2;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}

ll gcd(ll a, ll b) {
	if (a < b)swap(a, b);
	while (b) {
		ll r = a % b; a = b; b = r;
	}
	return a;
}

struct SegT {
private:
	int sz; vector<int> node;
	const int init_c = -mod;
public:
	SegT(vector<int> v) {
		int n = v.size();
		sz = 1;
		while (sz < n)sz *= 2;
		node.resize(2 * sz - 1, init_c);
		rep(i, n) {
			node[i + sz - 1] = v[i];
		}
		per(i, sz - 1) {
			node[i] = f(node[2 * i + 1], node[2 * i + 2]);
		}
	}
	SegT(int n) {
		sz = 1;
		while (sz < n)sz *= 2;
		node.resize(2 * sz - 1, init_c);
	}
	int f(int a, int b) {
		return max(a, b);
	}
	void update(int k, int a) {
		k += sz - 1;
		node[k] = a;
		while (k > 0) {
			k = (k - 1) / 2;
			node[k] = f(node[k * 2 + 1], node[k * 2 + 2]);
		}
	}
	int query(int a, int b, int k = 0, int l = 0, int r = -1) {
		if (r < 0)r = sz;
		if (r <= a || b <= l)return init_c;
		else if (a <= l && r <= b)return node[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 f(vl, vr);
		}
	}
};

void solve() {
	int h, w; cin >> h >> w;
	vector<int> a(h * w);
	rep(i, h * w)cin >> a[i];
	vector<int> t(h * w);
	rep(i, h * w)t[a[i]] = i;
	vector<bool> invy(h * w), invt(h * w);
	queue<int> q;
	vector<bool> used(h * w,false);
	used[0] = true; q.push(0);
	vector<int> vs;
	while (!q.empty()) {
		int v = q.front(); q.pop();
		vs.push_back(v);
		int x = a[v] / w;
		int y = a[v] % w;
		if (x - 1 >= 0) {
			int to = t[(x - 1) * w + y];
			if (!used[to])used[to] = true, q.push(to);
		}
		if (x + 1 < h) {
			int to = t[(x + 1) * w + y];
			if (!used[to])used[to] = true, q.push(to);
		}
		if (y - 1 >= 0) {
			int to = t[x * w + y-1];
			if (!used[to])used[to] = true, q.push(to);
		}
		if (y + 1 < w) {
			int to = t[x * w + y+1];
			if (!used[to])used[to] = true, q.push(to);
		}
	}
	fill(all(used), false);
	invy[0] = false;
	invt[0] = false;
	used[0] = true;
	vector<P> seg[4];
	rep(i, vs.size()) {
		//cout << vs[i] << "\n";
		int v = vs[i];
		int x = a[v] / w;
		int y = a[v] % w;
		if (y - 1 >= 0) {
			int to = t[x * w + y-1];
			bool by = false, bt = false;
			if (!invy[v]) {
				by = true;
				if(!used[to])seg[0].push_back(minmax(v, to));
			}
			else {
				by = false;
				if(!used[to])seg[1].push_back(minmax(v, to));
			}
			bt = invt[v];
			if (used[to]) {
				if (invy[to] != by || invt[to] != bt) {
					cout << "NO\n"; return;
				}
			}
			else {
				used[to] = true;
				invy[to] = by, invt[to] = bt;
			}
		}
		if (y + 1 < w) {
			int to = t[x * w + y + 1];
			bool by = false, bt = false;
			if (!invy[v]) {
				by = true;
				if(!used[to])seg[1].push_back(minmax(v, to));
			}
			else {
				by = false;
				if(!used[to])seg[0].push_back(minmax(v, to));
			}
			bt = invt[v];
			if (used[to]) {
				if (invy[to] != by || invt[to] != bt) {
					cout << "NO\n"; return;
				}
			}
			else {
				used[to] = true;
				invy[to] = by, invt[to] = bt;
			}
		}
		if (x - 1 >= 0) {
			int to = t[(x - 1) * w + y];
			bool by = false, bt = false;
			if (!invt[v]) {
				bt = true;
				if(!used[to])seg[2].push_back(minmax(v, to));
			}
			else {
				bt = false;
				if(!used[to])seg[3].push_back(minmax(v, to));
			}
			by = invy[v];
			if (used[to]) {
				if (invy[to] != by || invt[to] != bt) {
					cout << "NO\n"; return;
				}
			}
			else {
				used[to] = true;
				invy[to] = by, invt[to] = bt;
			}
		}
		if (x + 1 < h) {
			int to = t[(x + 1) * w + y];
			bool by = false, bt = false;
			if (!invt[v]) {
				bt = true;
				if(!used[to])seg[3].push_back(minmax(v, to));
			}
			else {
				bt = false;
				if(!used[to])seg[2].push_back(minmax(v, to));
			}
			by = invy[v];
			if (used[to]) {
				if (invy[to] != by || invt[to] != bt) {
					cout << "NO\n"; return;
				}
			}
			else {
				used[to] = true;
				invy[to] = by, invt[to] = bt;
			}
		}
	}
	rep(i, 4) {
		vector<P> s = seg[i];
		//cout << "hello\n";
		//rep(j, s.size())cout << s[j].first << " " << s[j].second << "\n";
		sort(all(s));
		vector<int> ori(h * w);
		rep(j, s.size()) {
			int le = j;
			while (j + 1 < s.size() && s[j + 1].first == s[j].first)j++;
			if (le != j) {
				cout << "NO\n"; return;
			}
			ori[s[j].first] = s[j].second;
		}
		SegT st(ori);
		rep(j, s.size()) {
			int q = st.query(s[j].first + 1, s[j].second);
			if (q >= s[j].second) {
				cout << "NO\n"; return;
			}
		}
	}
	cout << "YES\n";
}





signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(10);
	//init_f();
	//init();
	//expr();
	//int t; cin >> t; rep(i, t)
	solve();
	return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 14104
final_rank: 5

code_snippet: #include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 1000000007;
const ll INF = mod * mod;
typedef pair<int, int>P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-12;
const ld pi = acos(-1.0);

ll mod_pow(ll x, ll n, ll m = mod) {
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	ll n;
	modint() :n(0) { ; }
	modint(ll m) :n(m) {
		if (n >= mod)n %= mod;
		else if (n < 0)n = (n % mod + mod) % mod;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }

const int max_n = 1 << 2;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}

ll gcd(ll a, ll b) {
	if (a < b)swap(a, b);
	while (b) {
		ll r = a % b; a = b; b = r;
	}
	return a;
}

struct SegT {
private:
	int sz; vector<int> node;
	const int init_c = -mod;
public:
	SegT(vector<int> v) {
		int n = v.size();
		sz = 1;
		while (sz < n)sz *= 2;
		node.resize(2 * sz - 1, init_c);
		rep(i, n) {
			node[i + sz - 1] = v[i];
		}
		per(i, sz - 1) {
			node[i] = f(node[2 * i + 1], node[2 * i + 2]);
		}
	}
	SegT(int n) {
		sz = 1;
		while (sz < n)sz *= 2;
		node.resize(2 * sz - 1, init_c);
	}
	int f(int a, int b) {
		return max(a, b);
	}
	void update(int k, int a) {
		k += sz - 1;
		node[k] = a;
		while (k > 0) {
			k = (k - 1) / 2;
			node[k] = f(node[k * 2 + 1], node[k * 2 + 2]);
		}
	}
	int query(int a, int b, int k = 0, int l = 0, int r = -1) {
		if (r < 0)r = sz;
		if (r <= a || b <= l)return init_c;
		else if (a <= l && r <= b)return node[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 f(vl, vr);
		}
	}
};

void solve() {
	int h, w; cin >> h >> w;
	vector<int> a(h * w);
	rep(i, h * w)cin >> a[i];
	vector<int> t(h * w);
	rep(i, h * w)t[a[i]] = i;
	vector<bool> invy(h * w), invt(h * w);
	queue<int> q;
	vector<bool> used(h * w,false);
	used[0] = true; q.push(0);
	vector<int> vs;
	while (!q.empty()) {
		int v = q.front(); q.pop();
		vs.push_back(v);
		int x = a[v] / w;
		int y = a[v] % w;
		if (x - 1 >= 0) {
			int to = t[(x - 1) * w + y];
			if (!used[to])used[to] = true, q.push(to);
		}
		if (x + 1 < h) {
			int to = t[(x + 1) * w + y];
			if (!used[to])used[to] = true, q.push(to);
		}
		if (y - 1 >= 0) {
			int to = t[x * w + y-1];
			if (!used[to])used[to] = true, q.push(to);
		}
		if (y + 1 < w) {
			int to = t[x * w + y+1];
			if (!used[to])used[to] = true, q.push(to);
		}
	}
	fill(all(used), false);
	invy[0] = false;
	invt[0] = false;
	used[0] = true;
	vector<P> seg[4];
	rep(i, vs.size()) {
		//cout << vs[i] << "\n";
		int v = vs[i];
		int x = a[v] / w;
		int y = a[v] % w;
		if (y - 1 >= 0) {
			int to = t[x * w + y-1];
			bool by = false, bt = false;
			if (!invy[v]) {
				by = true;
				if(!used[to])seg[0].push_back(minmax(v, to));
			}
			else {
				by = false;
				if(!used[to])seg[1].push_back(minmax(v, to));
			}
			bt = invt[v];
			if (used[to]) {
				if (invy[to] != by || invt[to] != bt) {
					cout << "NO\n"; return;
				}
			}
			else {
				used[to] = true;
				invy[to] = by, invt[to] = bt;
			}
		}
		if (y + 1 < w) {
			int to = t[x * w + y + 1];
			bool by = false, bt = false;
			if (!invy[v]) {
				by = true;
				if(!used[to])seg[1].push_back(minmax(v, to));
			}
			else {
				by = false;
				if(!used[to])seg[0].push_back(minmax(v, to));
			}
			bt = invt[v];
			if (used[to]) {
				if (invy[to] != by || invt[to] != bt) {
					cout << "NO\n"; return;
				}
			}
			else {
				used[to] = true;
				invy[to] = by, invt[to] = bt;
			}
		}
		if (x - 1 >= 0) {
			int to = t[(x - 1) * w + y];
			bool by = false, bt = false;
			if (!invt[v]) {
				bt = true;
				if(!used[to])seg[2].push_back(minmax(v, to));
			}
			else {
				bt = false;
				if(!used[to])seg[3].push_back(minmax(v, to));
			}
			by = invy[v];
			if (used[to]) {
				if (invy[to] != by || invt[to] != bt) {
					cout << "NO\n"; return;
				}
			}
			else {
				used[to] = true;
				invy[to] = by, invt[to] = bt;
			}
		}
		if (x + 1 < h) {
			int to = t[(x + 1) * w + y];
			bool by = false, bt = false;
			if (!invt[v]) {
				bt = true;
				if(!used[to])seg[3].push_back(minmax(v, to));
			}
			else {
				bt = false;
				if(!used[to])seg[2].push_back(minmax(v, to));
			}
			by = invy[v];
			if (used[to]) {
				if (invy[to] != by || invt[to] != bt) {
					cout << "NO\n"; return;
				}
			}
			else {
				used[to] = true;
				invy[to] = by, invt[to] = bt;
			}
		}
	}
	rep(i, 4) {
		vector<P> s = seg[i];
		//cout << "hello\n";
		//rep(j, s.size())cout << s[j].first << " " << s[j].second << "\n";
		sort(all(s));
		vector<int> ori(h * w);
		rep(j, s.size()) {
			int le = j;
			while (j + 1 < s.size() && s[j + 1].first == s[j].first)j++;
			if (le != j) {
				cout << "NO\n"; return;
			}
			ori[s[j].first] = s[j].second;
		}
		SegT st(ori);
		rep(j, s.size()) {
			int q = st.query(s[j].first + 1, s[j].second);
			if (q >= s[j].second) {
				cout << "NO\n"; return;
			}
		}
	}
	cout << "YES\n";
}





signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(10);
	//init_f();
	//init();
	//expr();
	//int t; cin >> t; rep(i, t)
	solve();
	return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 13852
final_rank: 4

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> P;

int H,W;
int t[250000];
int u[250001];
bool rh[250001];
bool rw[250001];

int dy[]={-1,0,1,0};
int dx[]={0,1,0,-1};

bool solve(){
  int sy=t[0]/W;
  int sx=t[0]%W;
  for(int i=1;i<H*W;i++){
    int y=t[i]/W;
    int x=t[i]%W;
    if( abs(y-sy)%2 == 1 )rh[ t[i] ]=true;
    if( abs(x-sx)%2 == 1 )rw[ t[i] ]=true;
  }
  
  int last=-1;
  stack<int> total;
  stack<int> st[4];
  
  for(int i=0;i<H*W;i++){
    int n=t[i];
    vector<P> v;
    for(int dir=0;dir<4;dir++){
      int y=n/W+dy[dir];
      int x=n%W+dx[dir];
      if(y<0||H<=y)continue;
      if(x<0||W<=x)continue;
      int m=y*W+x;
      v.push_back(P(u[m],dir));
    }
    
    sort(v.begin(),v.end());
    reverse(v.begin(),v.end());
    
    for(int j=0;j<(int)v.size();j++){
      int dir=v[j].second;
      int y=n/W+dy[dir];
      int x=n%W+dx[dir];
      int m=y*W+x;
      int ndir=dir;
      if(rh[n]&&ndir%2==0)ndir=(ndir+2)%4;
      if(rw[n]&&ndir%2==1)ndir=(ndir+2)%4;
      stack<int> &w=st[ndir];
      if(u[m]<i){
        //        cout<<"pop  "<<n<<' '<<m<<' '<<ndir<<endl;
        if(w.empty()||w.top()!=n)return false;
        w.pop();
        //        if(total.top()<last)return false;
        total.pop();
        last=i;
      }
    }
    
    for(int j=0;j<(int)v.size();j++){
      int dir=v[j].second;
      int y=n/W+dy[dir];
      int x=n%W+dx[dir];
      int m=y*W+x;
      int ndir=dir;
      if(rh[n]&&ndir%2==0)ndir=(ndir+2)%4;
      if(rw[n]&&ndir%2==1)ndir=(ndir+2)%4;
      stack<int> &w=st[ndir];
      if(u[m]>=i){
        //        cout<<"push "<<n<<' '<<m<<' '<<ndir<<endl;
        w.push(m);
        total.push(i);
      }
    }
  }
  return true;
}

int main(){
  cin>>H>>W;
  for(int i=0;i<H*W;i++){
    cin>>t[i];
    u[t[i]]=i;
  }
  cout<<(solve()?"YES":"NO")<<endl;
  return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 5916
final_rank: 3

code_snippet: #include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define rep1(i,n) for(int i=1;i<=(int)(n);i++)
#define all(c) c.begin(),c.end()
#define pb push_back
#define fs first
#define sc second
#define show(x) cout << #x << " = " << x << endl
#define chmin(x,y) x=min(x,y)
#define chmax(x,y) x=max(x,y)
using namespace std;
template<class S,class T> ostream& operator<<(ostream& o,const pair<S,T> &p){return o<<"("<<p.fs<<","<<p.sc<<")";}
template<class T> ostream& operator<<(ostream& o,const vector<T> &vc){o<<"sz = "<<vc.size()<<endl<<"[";for(const T& v:vc) o<<v<<",";o<<"]";return o;}
int H,W;
typedef pair<int,int> P;
int ids[500*500];
bool ok(vector<P> vp){
	rep(i,H*W) ids[i]=0;
	int N=vp.size();
	rep(i,N){
		int in=vp[i].fs,out=vp[i].sc;
		if(in>out) swap(in,out);
		ids[in]=i+1;
		ids[out]=-(i+1);
	}
	stack<int> st;
	rep(i,H*W) if(ids[i]!=0){
		int x=ids[i];
		if(x>0){
			st.push(x);
		}else{
			int y=st.top();st.pop();
			if(-x!=y) return 0;
		}
	}
	return 1;
}
int p[500*500];
bool solve(){
	cin>>H>>W;
	rep(i,H*W){
		int a;
		cin>>a;
		p[a]=i;
	}
	vector<P> vp[2];
	rep(i,H) rep(j,W-1){
		vp[j%2].pb(P(p[i*W+j],p[i*W+j+1]));
	}
	if(!ok(vp[0])||!ok(vp[1])) return 0;
	vp[0].clear(),vp[1].clear();
	rep(j,W) rep(i,H-1){
		vp[i%2].pb(P(p[i*W+j],p[(i+1)*W+j]));
	}
	if(!ok(vp[0])||!ok(vp[1])) return 0;
	return 1;
}
int main(){
	if(solve()) puts("YES");
	else puts("NO");
}
accuracy: 1
time_ms: 60
memory_kb: 8796
final_rank: 2

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>

using namespace std;
using ll = long long;
constexpr ll TEN(int n) { return (n == 0) ? 1 : 10LL * TEN(n-1); }

using P = pair<int, int>;
bool ok(vector<P> v) {
    for (auto &p: v) {
        if (p.first > p.second) {
            swap(p.first, p.second);
        }
    }
    sort(begin(v), end(v));
    vector<P> st;
    for (auto p: v) {
        while (st.size() && st.back().second < p.first) {
            st.pop_back();
        }
        if (st.size() && st.back().second < p.second) {
            return false;
        }
        st.push_back(p);
    }
    return true;
}

int main() {
    int h, w;
    scanf("%d %d", &h, &w);
    int n = h*w;
    int rid[n];
    for (int i = 0; i < n; i++) {
        int a;
        cin >> a;
        rid[a] = i;
    }

    for (int y = 0; y < h; y++) {
        vector<P> v[2];
        for (int x = 0; x < w-1; x++) {
            int id = y*w+x;
            v[x%2].push_back(P(rid[id], rid[id+1]));
        }
        if (!ok(v[0]) || !ok(v[1])) {
            cout << "NO" << endl;
            return 0;
        }
    }

    for (int x = 0; x < w; x++) {
        vector<P> v[2];
        for (int y = 0; y < h-1; y++) {
            int id = y*w+x;
            v[y%2].push_back(P(rid[id], rid[id+w]));
        }
        if (!ok(v[0]) || !ok(v[1])) {
            cout << "NO" << endl;
            return 0;
        }        
    }
    cout << "YES" << endl;
    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 4200
final_rank: 1