【题目链接】
- 点击打开链接
【思路要点】
- 考虑模拟最短路算法的过程,需要维护一个二维点集,支持矩形 c h k m i n chkmin chkmin ,询问全局最小值,单点删除,并且不能占用过多空间。
- 显然可以用 K D − T r e e KD-Tree KD−Tree 解决。
- 时间复杂度 O ( M N ) O(M\sqrt{N}) O(MN) ,空间复杂度 O ( N ) O(N) O(N) 。
【代码】
#include
using namespace std; const int MAXN = 1e5 + 5; const int INF = 1e9; typedef long long ll; template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -f; for (; isdigit(ch); ch= getchar()) x = x * 10 + ch - '0'; x *= f; } struct point {int x, y; } p[MAXN]; point min(point a, point b) {return (point) {min(a.x, b.x), min(a.y, b.y)}; } point max(point a, point b) {return (point) {max(a.x, b.x), max(a.y, b.y)}; } bool cmptype; bool cmp(point a, point b) { if (cmptype) return a.x < b.x || (a.x == b.x && a.y < b.y); else return a.y < b.y || (a.y == b.y && a.x < b.x); } bool cnp(int a, int b) { return cmp(p[a], p[b]); } struct edge {int len; point a, b; }; vector <edge> e[MAXN]; int n, m, w, h, home[MAXN], ans[MAXN]; struct Tree { struct Node { point pos, rl, rr; int lc, rc; int home, tag, Min, Max, Val, vis; } a[MAXN]; int root, size, n; void updateval(int root) { if (!a[root].vis) { a[root].Min = a[root].Val; a[root].Max = a[root].Val; } else { a[root].Min = INF; a[root].Max = 0; } if (a[root].lc) { chkmin(a[root].Min, a[a[root].lc].Min); chkmax(a[root].Max, a[a[root].lc].Max); } if (a[root].rc) { chkmin(a[root].Min, a[a[root].rc].Min); chkmax(a[root].Max, a[a[root].rc].Max); } } void update(int root) { if (!a[root].vis) { a[root].Min = a[root].Val; a[root].Max = a[root].Val; a[root].rl = a[root].rr = a[root].pos; } else { a[root].Min = INF; a[root].Max = 0; a[root].rl = (point) {INF, INF}; a[root].rr = (point) {-INF, -INF}; } if (a[root].lc) { chkmin(a[root].Min, a[a[root].lc].Min); chkmax(a[root].Max, a[a[root].lc].Max); chkmin(a[root].rl, a[a[root].lc].rl); chkmax(a[root].rr, a[a[root].lc].rr); } if (a[root].rc) { chkmin(a[root].Min, a[a[root].rc].Min); chkmax(a[root].Max, a[a[root].rc].Max); chkmin(a[root].rl, a[a[root].rc].rl); chkmax(a[root].rr, a[a[root].rc].rr); } } int build(int l, int r, bool type) { cmptype = type; int mid = (l + r) / 2, root = ++size; nth_element(home + l, home + mid, home + r + 1, cnp); a[root].Val = INF, a[root].vis = false; a[root].pos = p[home[mid]]; a[root].home = home[mid]; a[root].tag = INF; if (a[root].home == 1) a[root].Val = 0; if (l < mid) a[root].lc = build(l, mid - 1, type ^ true); if (mid < r) a[root].rc = build(mid + 1, r, type ^ true); update(root); return root; } void init(int x) { n = x; for (int i = 1; i <= n; i++) home[i] = i; root = build(1, n, true); } void addtag(int root, int val) { if (val < a[root].Max && val < a[root].tag) { a[root].tag = val; a[root].Max = val; chkmin(a[root].Min, val); if (!a[root].vis) chkmin(a[root].Val, val); } } void pushdown(int root) { if (a[root].tag != INF) { if (a[root].lc) addtag(a[root].lc, a[root].tag); if (a[root].rc) addtag(a[root].rc, a[root].tag); a[root].tag = INF; } } int findpos(int root, int val) { pushdown(root); if (!a[root].vis && a[root].Val == val) { a[root].vis = true; update(root); return root; } if (a[root].lc && a[a[root].lc].Min == val) { int ans = findpos(a[root].lc, val); update(root); return ans; } else { assert(a[root].rc && a[a[root].rc].Min == val); int ans = findpos(a[root].rc, val); update(root); return ans; } } void modify(int root, int len, point ql, point qr) { pushdown(root); if (len >= a[root].Max) return; if (ql.x > a[root].rr.x || qr.x < a[root].rl.x || ql.y > a[root].rr.y || qr.y < a[root].rl.y) return; if (ql.x <= a[root].rl.x && ql.y <= a[root].rl.y && qr.x >= a[root].rr.x && qr.y >= a[root].rr.y) { addtag(root, len); return; } if (!a[root].vis && ql.x <= a[root].pos.x && ql.y <= a[root].pos.y && qr.x >= a[root].pos.x && qr.y >= a[root].pos.y) chkmin(a[root].Val, len); if (a[root].lc) modify(a[root].lc, len, ql, qr); if (a[root].rc) modify(a[root].rc, len, ql, qr); updateval(root); } void getans() { for (int i = 1; i <= n; i++) { int pos = findpos(root, a[root].Min); ans[a[pos].home] = a[pos].Val; int home = a[pos].home; for (unsigned j = 0; j < e[home].size(); j++) modify(root, e[home][j].len + a[pos].Val, e[home][j].a, e[home][j].b); } for (int i = 2; i <= n; i++) printf("%d\n", ans[i]); } } T; int main() { freopen("jump.in", "r", stdin); freopen("jump.out", "w", stdout); read(n), read(m), read(w), read(h); for (int i = 1; i <= n; i++) read(p[i].x), read(p[i].y); for (int i = 1; i <= m; i++) { int from, len, l, r, d, u; read(from), read(len), read(l), read(r), read(d), read(u); e[from].push_back((edge) {len, (point) {l, d}, (point) {r, u}}); } T.init(n); T.getans(); return 0; }