Problem:
Problem K: Move on Ice

Problem

ペンギンのフロロは無限に広い氷の上のマス($sx$,$sy$)にいる。

マス($tx$,$ty$)に穴があり、そこから水に入ることができる。

氷の上に$n$個の氷の塊があり、それぞれマス($x_i$,$y_i$)にある。

フロロは上下左右の4方向に移動できる。

氷の上は滑りやすいので、移動すると氷の塊にぶつかるまで動き続ける。

氷の塊にぶつかると氷の塊のあるマスの1マス手前で止まる。

穴のマスを通過することで穴に入ることができる。

フロロは1度だけ全力で踏ん張ることにより途中で止まることができる。

氷の塊にぶつかると痛いのでできるだけぶつかる回数を少なくしたい。

穴のあるマス($tx$,$ty$)へ移動するまでにぶつかる回数の最小値を求めよ。

辿り着けない場合は$-$1を出力せよ。

Input

入力は以下の形式で与えられる。

$sx$ $sy$
$tx$ $ty$
$n$
$x_1$ $y_1$
...
$x_n$ $y_n$

入力はすべて整数で与えられる。

1行目にフロロがいるマスの座標が空白区切りで与えられる。

2行目に穴があるマスの座標が空白区切りで与えられる。

3行目に氷の塊の数$n$が与えられる。

続く$n$行目に氷の塊があるマスの座標が空白区切りで与えられる。

Constraints

入力は以下の条件を満たす。

$0 \leq n \leq 10^5$

$0 \leq sx$,$sy$,$tx$,$ty$,$x_i$,$y_i \leq 10^9$

与えられる座標はすべて異なる

Output

穴に移動するまでにぶつかる回数の最小値を出力せよ。

辿り着けない場合は$-$1を出力せよ。

Sample Input 1

0 0
13 33
2
0 34
14 0

Sample Output 1

0

Sample Input 2

0 1
5 0
4
2 1
1 3
4 2
3 0

Sample Output 2

4

Sample Input 3

0 0
0 2
1
0 1

Sample Output 3

-1

Solution in C++14 (judge verdict: Wrong Answer)

#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<complex>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<utility>
using namespace std;
typedef long long ll;
typedef unsigned int ui;
const ll mod = 1000000007;
const ll INF = (ll)1000000007 * 1000000007;
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++)
typedef long double ld;
typedef complex<ld> Point;
const ld eps = 1e-6;
const ld pi = acos(-1.0);
typedef pair<ll, ll> LP;

int n;
int sx, sy, gx, gy;

struct vertice {
	int x, y, f;
	bool operator<(const vertice &v)const {
		if (x != v.x)return x < v.x;
		if (y != v.y)return y < v.y;
		return f < v.f;
	}
	bool operator==(const vertice &v)const {
		if (x == v.x&&y == v.y&&f == v.f)return true;
		return false;
	}
};

void compress(vector<vertice> &v) {
	int n = v.size();
	vector<LP> x, y;
	rep(i, n) {
		x.push_back({ v[i].x,i });
		y.push_back({ v[i].y,i });
	}
	sort(x.begin(), x.end());
	sort(y.begin(), y.end());
	int cur = 0;
	rep(i, n) {
		v[x[i].second].x = cur;
		while (i + 1 < n&&x[i].first == x[i + 1].first) {
			i++; v[x[i].second].x = cur;
		}
		cur++;
	}
	cur = 0;
	rep(i, n) {
		v[y[i].second].y = cur;
		while (i + 1 < n&&y[i].first == y[i + 1].first) {
			i++; v[y[i].second].y = cur;
		}
		cur++;
	}
}

vector<vertice> v; map<P, int> inv;

const int mn = 500005;
vector<P> cx[mn], cy[mn];

int d[2][mn];
priority_queue<P, vector<P>, greater<P>> q;
vector<int> G[mn];
void dijkstra(int id, int root) {
	d[id][root] = 0;
	q.push({ 0,root });
	while (!q.empty()) {
		P p = q.top(); q.pop();
		int i = p.second; int dist = p.first;
		int x = v[i].x, y = v[i].y;
		//x軸
		int loc = lower_bound(cx[x].begin(), cx[x].end(), P{ y,-1 }) - cx[x].begin();
		loc--;
		if (loc >= 0 && loc < cx[x].size()) {
			int ni = cx[x][loc].second;
			if (v[ni].f == 0) {
				ni = inv[{x, cx[x][loc].first + 1}];
				if (dist + 1 < d[id][ni]) {
					d[id][ni] = dist + 1;
					G[ni].push_back(i);
					q.push({ d[id][ni],ni });
				}
			}
			else {
				d[id][ni] = min(d[id][ni], dist);
				G[ni].push_back(i);
			}
		}
		loc++;
		if (v[i].f >= 2)loc++;
		if (loc < cx[x].size()) {
			int ni = cx[x][loc].second;
			if (v[ni].f == 0) {
				ni = inv[{x, cx[x][loc].first - 1}];
				if (dist + 1 < d[id][ni]) {
					d[id][ni] = dist + 1;
					q.push({ d[id][ni],ni });
					G[ni].push_back(i);
				}
			}
			else {
				d[id][ni] = min(d[id][ni], dist);
				G[ni].push_back(i);
			}
		}
		//y軸
		loc = lower_bound(cy[y].begin(), cy[y].end(), P{ x,-1 }) - cy[y].begin();
		loc--;
		if (loc >= 0 && loc<cy[y].size()) {
			int ni = cy[y][loc].second;
			if (v[ni].f == 0) {
				ni = inv[{cy[y][loc].first + 1, y}];
				if (dist + 1 < d[id][ni]) {
					d[id][ni] = dist + 1;
					q.push({ d[id][ni],ni });
					G[ni].push_back(i);
				}
			}
			else {
				d[id][ni] = min(d[id][ni], dist);
				G[ni].push_back(i);
			}
		}
		loc++;
		if (v[i].f >= 2)loc++;
		if (loc < cy[y].size()) {
			int ni = cy[y][loc].second;
			if (v[ni].f == 0) {
				ni = inv[{cy[y][loc].first - 1, y}];
				if (dist + 1 < d[id][ni]) {
					d[id][ni] = dist + 1;
					q.push({ d[id][ni],ni });
					G[ni].push_back(i);
				}
			}
			if (dist + 1 < d[id][ni]) {
				d[id][ni] = min(d[id][ni], dist);
				G[ni].push_back(i);
			}
		}
	}
}
int sid;
void invdijkstra(int root) {
	d[1][root] = 0;
	q.push({ 0,root });
	while (!q.empty()) {
		P p = q.top(); q.pop();
		int i = p.second;
		rep(j, G[i].size()) {
			int to = G[i][j];
			if (to == sid)d[1][sid] = min(d[1][sid], p.first);
			else {
				if (p.first + 1 < d[1][to]) {
					d[1][to] = p.first + 1;
					q.push({ d[1][to],to });
				}
			}
		}
	}
}
int ans = mod;

struct SegT {
private:
	int sz; vector<int> node;
	const int init_c = mod;
public:
	SegT(int n) {
		sz = 1;
		while (sz < n)sz *= 2;
		node.resize(2 * sz - 1, init_c);
	}
	int f(int a, int b) {
		return min(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);
		}
	}
};
int len;

//全頂点が入ってるほう
vector<P> ux[mn], uy[mn];
//下から
void calc1() {
	SegT st(mn);
	rep(i, mn) {
		rep(j, ux[i].size()) {
			int le = 0, ri = mn;
			int x = i, y = ux[i][j].first;
			int loc = lower_bound(cx[x].begin(), cx[x].end(), P{ y,-1 }) - cx[x].begin();
			loc--;
			if (loc >= 0 && loc<cx[x].size()) {
				le = cx[x][loc].first + 1;
			}
			loc++;
			int nowi = ux[i][j].second;
			if (v[nowi].f >= 2)loc++;
			if (loc < cx[x].size()) {
				ri = cx[x][loc].first;
			}
			int z = st.query(le, ri);
			ans = min(ans, z + d[0][ux[i][j].second]);
		}
		rep(j, cx[i].size()) {
			int id = cx[i][j].second;
			if (v[id].f == 2)continue;
			if (v[id].f == 3) {
				st.update(cx[i][j].first, d[1][id]);
			}
			else {
				st.update(cx[i][j].first, d[1][id] + 1);
			}
		}
	}
}
//上から
void calc2() {
	SegT st(mn);
	per(i, mn) {
		rep(j, ux[i].size()) {
			int le = 0, ri = mn;
			int x = i, y = ux[i][j].first;
			int loc = lower_bound(cx[x].begin(), cx[x].end(), P{ y,-1 }) - cx[x].begin();
			loc--;
			if (loc >= 0 && loc<cx[x].size()) {
				le = cx[x][loc].first + 1;
			}
			loc++;
			int nowi = ux[i][j].second;
			if (v[nowi].f >= 2)loc++;
			if (loc < cx[x].size()) {
				ri = cx[x][loc].first;
			}
			int z = st.query(le, ri);
			ans = min(ans, z + d[0][ux[i][j].second]);
		}
		rep(j, cx[i].size()) {
			int id = cx[i][j].second;
			if (v[id].f == 2)continue;
			if (v[id].f == 3) {
				st.update(cx[i][j].first, d[1][id]);
			}
			else {
				st.update(cx[i][j].first, d[1][id] + 1);
			}
		}
	}
}
void calc3() {
	SegT st(mn);
	rep(i, mn) {
		rep(j, uy[i].size()) {
			int le = 0, ri = mn;
			int x = uy[i][j].first, y = i;
			int loc = lower_bound(cy[y].begin(), cy[y].end(), P{ x,-1 }) - cy[y].begin();
			loc--;
			if (loc >= 0 && loc<cy[y].size()) {
				le = cy[y][loc].first + 1;
			}
			loc++;
			int nowi = uy[i][j].second;
			if (v[nowi].f >= 2)loc++;
			if (loc < cy[y].size()) {
				ri = cy[y][loc].first;
			}
			int z = st.query(le, ri);
			ans = min(ans, z + d[0][uy[i][j].second]);
		}
		rep(j, cy[i].size()) {
			int id = cy[i][j].second;
			if (v[id].f == 2)continue;
			if (v[id].f == 3) {
				st.update(cy[i][j].first, d[1][id]);
			}
			else {
				st.update(cy[i][j].first, d[1][id] + 1);
			}
		}
	}
}
void calc4() {
	SegT st(mn);
	per(i, mn) {
		rep(j, uy[i].size()) {
			int le = 0, ri = mn;
			int x = uy[i][j].first, y = i;
			int loc = lower_bound(cy[y].begin(), cy[y].end(), P{ x,-1 }) - cy[y].begin();
			loc--;
			if (loc >= 0 && loc<cy[y].size()) {
				le = cy[y][loc].first + 1;
			}
			loc++;
			int nowi = uy[i][j].second;
			if (v[nowi].f >= 2)loc++;
			if (loc < cy[y].size()) {
				ri = cy[y][loc].first;
			}
			int z = st.query(le, ri);
			ans = min(ans, z + d[0][uy[i][j].second]);
		}
		rep(j, cy[i].size()) {
			int id = cy[i][j].second;
			if (v[id].f == 2)continue;
			if (v[id].f == 3) {
				st.update(cy[i][j].first, d[1][id]);
			}
			else {
				st.update(cy[i][j].first, d[1][id] + 1);
			}
		}
	}
}
void calc() {
	calc1(); calc2(); calc3(); calc4();
	if (ans >= mod)cout << -1 << endl;
	else cout << ans << endl;
	return;
}
int main() {
	cin >> sx >> sy >> gx >> gy;
	cin >> n;
	rep(i, n) {
		int x, y; cin >> x >> y;
		v.push_back({ x,y,0 });
		v.push_back({ x + 1,y,1 });
		v.push_back({ x - 1,y,1 });
		v.push_back({ x,y + 1,1 });
		v.push_back({ x,y - 1,1 });
	}
	v.push_back({ sx,sy,2 });
	v.push_back({ gx,gy,3 });
	compress(v);
	sort(v.begin(), v.end());
	len = unique(v.begin(), v.end()) - v.begin();

	int gid;
	rep(i, len) {
		inv[{v[i].x, v[i].y}] = i;

	}
	rep(i, len) {
		if (v[i].f == 2) {
			sid = i;
			inv[{v[i].x, v[i].y}] = i;
		}
		else if (v[i].f == 3) {
			gid = i;
			inv[{v[i].x, v[i].y}] = i;
		}
	}
	rep(i, len) {
		int x = v[i].x, y = v[i].y, f = v[i].f;
		if (f == 1)continue;
		cx[x].push_back({ y,i });
		cy[y].push_back({ x,i });
	}
	rep(i, len) {
		int x = v[i].x, y = v[i].y, f = v[i].f;
		if (f == 0)continue;
		ux[x].push_back({ y,i });
		uy[y].push_back({ x,i });

	}
	rep(i, mn) {
		sort(cx[i].begin(), cx[i].end());
		sort(cy[i].begin(), cy[i].end());
		sort(ux[i].begin(), ux[i].end());
		sort(uy[i].begin(), uy[i].end());
	}

	//dijkstra
	rep(i, 2)rep(j, mn)d[i][j] = mod;
	dijkstra(0, sid); invdijkstra(gid);
	ans = d[0][gid];
	calc();

	//stop
	return 0;
}