BZOJ 1941. [Sdoi2010]Hide and Seek
KD-tree 板子题。
#include <bits/stdc++.h> namespace IO { char buf[1 << 21], *p1 = buf, *p2 = buf; void read() {} inline int getc() { return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++; } template <typename T, typename... T2> inline void read(T &x, T2 &... oth) { T f = 1; x = 0; char ch = getc(); while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getc(); } while (isdigit(ch)) { x = x * 10 + ch - 48; ch = getc(); } x *= f; read(oth...); } } inline void checkmax(int &a, int b) { if (a < b) a = b; } inline void checkmin(int &a, int b) { if (a > b) a = b; } const int N = 1e6 + 7; const int INF = 0x3f3f3f3f; int n, m, D, root, ql, qr, mx, mn; struct Tree { int mn[2], mx[2]; int d[2]; int l, r; inline bool operator < (const Tree &rhs) const { if (d[D] == rhs.d[D]) return d[D ^ 1] < rhs.d[D ^ 1]; return d[D] < rhs.d[D]; } } tree[N * 2]; inline void pushup(int p, int k) { checkmin(tree[p].mn[0], tree[k].mn[0]); checkmin(tree[p].mn[1], tree[k].mn[1]); checkmax(tree[p].mx[0], tree[k].mx[0]); checkmax(tree[p].mx[1], tree[k].mx[1]); } int build(int l, int r, int d) { int mid = l + r >> 1; D = d; std::nth_element(tree + l, tree + mid, tree + r + 1); tree[mid].mn[0] = tree[mid].mx[0] = tree[mid].d[0]; tree[mid].mn[1] = tree[mid].mx[1] = tree[mid].d[1]; if (l != mid) tree[mid].l = build(l, mid - 1, d ^ 1), pushup(mid, tree[mid].l); if (r != mid) tree[mid].r = build(mid + 1, r, d ^ 1), pushup(mid, tree[mid].r); return mid; } inline int dis1(int p) { int res = 0; if (ql < tree[p].mn[0]) res += tree[p].mn[0] - ql; if (ql > tree[p].mx[0]) res += ql - tree[p].mx[0]; if (qr < tree[p].mn[1]) res += tree[p].mn[1] - qr; if (qr > tree[p].mx[1]) res += qr - tree[p].mx[1]; return res; } inline void query1(int p) { int d0 = std::abs(tree[p].d[0] - ql) + std::abs(tree[p].d[1] - qr); if (d0 < mn && d0) mn = d0; int dl = INF, dr = INF; if (tree[p].l) dl = dis1(tree[p].l); if (tree[p].r) dr = dis1(tree[p].r); if (dl < dr) { if (dl < mn) query1(tree[p].l); if (dr < mn) query1(tree[p].r); } else { if (dr < mn) query1(tree[p].r); if (dl < mn) query1(tree[p].l); } } inline int dis2(int p) { int res = 0; res += std::max(std::abs(tree[p].mn[0] - ql), std::abs(ql - tree[p].mx[0])) + std::max(std::abs(tree[p].mn[1] - qr), std::abs(qr - tree[p].mx[1])); return res; } inline void query2(int p) { int d0 = std::abs(tree[p].d[0] - ql) + std::abs(tree[p].d[1] - qr); if (d0 > mx) mx = d0; int dl = 0, dr = 0; if (tree[p].l) dl = dis2(tree[p].l); if (tree[p].r) dr = dis2(tree[p].r); if (dl > dr) { if (dl > mx) query2(tree[p].l); if (dr > mx) query2(tree[p].r); } else { if (dr > mx) query2(tree[p].r); if (dl > mx) query2(tree[p].l); } } int main() { IO::read(n); for (int i = 1; i <= n; i++) IO::read(tree[i].d[0], tree[i].d[1]); root = build(1, n, 0); int res = INF; for (int i = 1; i <= n; i++) { mx = 0, mn = INF; ql = tree[i].d[0], qr = tree[i].d[1]; query1(root); query2(root); res = std::min(res, mx - mn); } printf("%d\n", res); return 0; }