题面
解题思路
最朴素的想法是将图建出来跑最短路。
观察后发现如下两条性质:
1.边权是1,可以用广度优先搜索代替最短路。
2.因为是广度优先搜索,每条边只会被松弛一次。
但是图的大小可能是
n
2
n^2
n2级别的。我们考虑使用线段树维护隐式图来支持搜索。
复杂度
O
(
n
l
o
g
2
n
)
O(nlog_2n)
O(nlog2n)。
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
#define lson rt * 2
#define rson rt * 2 + 1
void read(int &x) {
x = 0; char c = getchar();
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
}
const int N = 1e5 + 100;
struct node {
int y, id;
node() {}
node(int y, int id) :y(y), id(id) {}
}tree[N * 4];
bool operator < (node a, node b) {
if (a.y == b.y) return a.id < b.id;
return a.y < b.y;
}
bool operator > (node a, node b) {
if (a.y == b.y) return a.id > b.id;
return a.y > b.y;
}
int n, tp;
int sx[N], sy[N], ex[N], ey[N], dis[N], has[N];
priority_queue<node, vector<node>, greater<node> > P[N * 4];
queue<int> Q;
void build(int l, int r, int rt) {
tree[rt] = node(2e9, 0);
if (l == r) return;
int m = (l + r) / 2;
build(l, m, lson);
build(m + 1, r, rson);
}
void insert(int id, int l, int r, int rt) {
if (l == r) {
P[rt].push(node(sy[id], id));
tree[rt] = P[rt].top();
return;
}
int m = (l + r) / 2;
if (sx[id] <= has[m]) insert(id, l, m, lson);
else insert(id, m + 1, r, rson);
tree[rt] = min(tree[lson], tree[rson]);
}
void query(int id, int l, int r, int rt) {
if (tree[rt].y > ey[id]) return;
if (l == r) {
while (!P[rt].empty() && P[rt].top().y <= ey[id]) {
dis[P[rt].top().id] = dis[id] + 1;
Q.push(P[rt].top().id);
P[rt].pop();
}
if (P[rt].empty()) tree[rt] = node(2e9, 0);
else tree[rt] = P[rt].top();
return;
}
int m = (l + r) / 2;
query(id, l, m, lson);
if (ex[id] >= has[m + 1]) query(id, m + 1, r, rson);
tree[rt] = min(tree[lson], tree[rson]);
}
int main() {
//freopen("0.txt", "r", stdin);
read(n);
for (int i = 1; i <= n; i++) {
read(sx[i]); read(sy[i]);
read(ex[i]); read(ey[i]);
has[i] = sx[i];
}
sort(has + 1, has + n + 1);
tp = unique(has + 1, has + n + 1) - has - 1;
for (int i = 1; i <= n; i++) insert(i, 1, tp, 1);
Q.push(0);
while (!Q.empty()) {
int u = Q.front(); Q.pop();
if (ex[u] >= has[1]) query(u, 1, tp, 1);
}
if (dis[n] == 0) dis[n] = -1;
printf("%d\n", dis[n]);
return 0;
}