bzoj 1941 [Sdoi2010]Hide and Seek 線段樹/kd-tree
阿新 • • 發佈:2018-12-11
題面
解法
可以考慮kd-tree,但是我並不會……
- 對於每一個,我們就是要求,類似
- 考慮分種情況,就是將絕對值拆開
- 不妨只考慮且的情況,其他3種情況是類似的
- 發現將絕對值展開後為,那麼我們按照從小到大排序,在相同的時候按照從小到大排
- 然後我們列舉,強制,然後用線段樹維護滿足在區間的的最小值
- 可以發現,即使在這種情況下可能不會被統計到,但是在其他情況中一定會被統計到,所以演算法是正確的
- 其實不一定要用線段樹,似乎樹狀陣列也可以完成這個工作
- 時間複雜度:
程式碼
#include <bits/stdc++.h>
#define inf 1 << 29
#define N 200010
using namespace std;
template <typename node> void chkmax(node &x, node y) {x = max(x, y);}
template <typename node> void chkmin(node &x, node y) {x = min(x, y);}
template <typename node> void read(node & x) {
x = 0; int f = 1; char c = getchar();
while (!isdigit(c)) {if (c == '-') f = -1; c = getchar();}
while (isdigit(c)) x = x * 10 + c - '0', c = getchar(); x *= f;
}
struct Point {
int x, y, id;
} a[N];
struct SegmentTree {
struct Node {
int lc, rc, mx, mn;
} t[N * 4];
int tot;
void Clear() {tot = 0, memset(t, 0, sizeof(t));}
void ins(int &k, int l, int r, int x, int v) {
if (!k) k = ++tot, t[k].mn = inf, t[k].mx = -inf;
chkmin(t[k].mn, v), chkmax(t[k].mx, v);
if (l == r) return; int mid = (l + r) >> 1;
if (x <= mid) ins(t[k].lc, l, mid, x, v);
else ins(t[k].rc, mid + 1, r, x, v);
}
pair <int, int> query(int k, int l, int r, int L, int R) {
if (!k) return make_pair(-inf, inf);
if (L <= l && r <= R) return make_pair(t[k].mx, t[k].mn);
int mid = (l + r) >> 1;
if (R <= mid) return query(t[k].lc, l, mid, L, R);
if (L > mid) return query(t[k].rc, mid + 1, r, L, R);
pair <int, int> tx = query(t[k].lc, l, mid, L, mid), ty = query(t[k].rc, mid + 1, r, mid + 1, R);
return make_pair(max(tx.first, ty.first), min(tx.second, ty.second));
}
} T;
bool cmp1(Point a, Point b) {return (a.x == b.x) ? a.y < b.y : a.x < b.x;}
bool cmp2(Point a, Point b) {return (a.x == b.x) ? a.y > b.y : a.x < b.x;}
bool cmp3(Point a, Point b) {return (a.x == b.x) ? a.y < b.y : a.x > b.x;}
bool cmp4(Point a, Point b) {return (a.x == b.x) ? a.y > b.y : a.x > b.x;}
int tx[N], mx[N], mn[N];
int main() {
int n, len = 0; read(n);
for (int i = 1; i <= n; i++)
read(a[i].x), read(a[i].y), tx[++len] = a[i].x, tx[++len] = a[i].y, a[i].id = i;
sort(tx + 1, tx + len + 1); len = unique(tx + 1, tx + len + 1) - tx - 1;
map <int, int> h;
for (int i = 1; i <= len; i++) h[tx[i]] = i;
for (int i = 1; i <= n; i++) a[i].x = h[a[i].x], a[i].y = h[a[i].y];
sort(a + 1, a + n + 1, cmp1), T.Clear(); int rt = 0;
for (int i = 1; i <= n; i++) mx[i] = -inf, mn[i] = inf;
for (int i = 1; i <= n; i++) {
pair <int, int> tmp = T.query(rt, 1, len, 1, a[i].y);
chkmax(mx[a[i].id], tx[a[i].x] + tx[a[i].y] - tmp.second);
chkmin(mn[a[i].id], tx[a[i].x] + tx[a[i].y] - tmp.first);
T.ins(rt, 1, len, a[i].y, tx[a[i].x] + tx[a[i].y]);
}
sort(a + 1, a + n + 1, cmp2), T.Clear(); rt = 0;
for (int i = 1; i <= n; i++) {
pair <int, int> tmp = T.query(rt, 1, len, a[i].y, len);
chkmax(mx[a[i].id], tx[a[i].x] - tx[a[i].y] - tmp.second);
chkmin(mn[a[i].id], tx[a[i].x] - tx[a[i].y] - tmp.first);
T.ins(rt, 1, len, a[i].y, tx[a[i].x] - tx[a[i].y]);
}
sort(a + 1, a + n + 1, cmp3), T.Clear(); rt = 0;
for (int i = 1; i <= n; i++) {
pair <int, int> tmp = T.query(rt, 1, len, 1, a[i].y);
chkmax(mx[a[i].id], -tx[a[i].x] + tx[a[i].y] - tmp.second);
chkmin(mn[a[i].id], -tx[a[i].x] + tx[a[i].y] - tmp.first);
T.ins(rt, 1, len, a[i].y, -tx[a[i].x] + tx[a[i].y]);
}
sort(a + 1, a + n + 1, cmp4), T.Clear(), rt = 0;
for (int i = 1; i <= n; i++) {
pair <int, int> tmp = T.query(rt, 1, len, a[i].y, len);
chkmax(mx[a[i].id], -tx[a[i].x] - tx[a[i].y] - tmp.second);
chkmin(mn[a[i].id], -tx[a[i].x] - tx[a[i].y] - tmp.first);
T.ins(rt, 1, len, a[i].y, -tx[a[i].x] - tx[a[i].y]);
}
int ans = inf;
for (int i = 1; i <= n; i++)
chkmin(ans, mx[i] - mn[i]);
cout << ans << "\n";
return 0;
}