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;
}
View Code

 

posted @ 2020-01-31 16:01  Mrzdtz220  阅读(87)  评论(0编辑  收藏  举报