[BZOJ2716][Violet 3]天使玩偶 && kdtree

存模板

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#define SF scanf
#define PF printf
#define mp make_pair
#define sqr(x) ((x)*(x))
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
using namespace std;
typedef long long LL;
const int MAXN = 500000;
const int INF = 0x3f3f3f3f;
struct Node {
    int d[2], mn[2], mx[2];
    int l, r;
    int operator [] (int x) const { return d[x]; }
    int & operator [] (int x) { return d[x]; }
    Node (int x = 0, int y = 0) {
        l = r = 0; d[0] = x; d[1] = y;
    }
} A[MAXN+10];
int direction;
bool operator < (const Node &a, const Node &b) {
    return a[direction] < b[direction];
}
inline LL dis(const Node &a, const Node &b) {
    return abs(a[0]-b[0])+abs(a[1]-b[1]);
}
struct kd_Tree {
    int ans;
    int ncnt, root;
    Node t[MAXN*2+10], T;
    inline void up(int x) {
        Node &u = t[x];
        Node l = t[u.l], r = t[u.r];
        for(int i = 0; i < 2; i++) {
            if(u.l) u.mn[i] = min(u.mn[i], l.mn[i]), u.mx[i] = max(u.mx[i], l.mx[i]);
            if(u.r) u.mn[i] = min(u.mn[i], r.mn[i]), u.mx[i] = max(u.mx[i], r.mx[i]);
        }
    }
    int build(int l, int r, int dir, Node *p) {
        direction = dir;
        int mid = (l+r) >> 1;
        nth_element(p+l, p+mid, p+r+1);
        t[mid] = p[mid];
        for(int i = 0; i < 2; i++)
            t[mid].mn[i] = t[mid].mx[i] = t[mid][i];
        if(l < mid) t[mid].l = build(l, mid-1, dir^1, p);
        if(r > mid) t[mid].r = build(mid+1, r, dir^1, p);
        up(mid);
        return mid;
    }
    inline void ins(int k, int dir) {
        Node &u = t[k];
        if(T[dir] >= u[dir]) {
            if(u.r) ins(u.r, dir^1);
            else {
                u.r = ++ncnt; t[ncnt] = T;
                for(int i = 0; i < 2; i++)
                    t[ncnt].mn[i] = t[ncnt].mx[i] = t[ncnt][i];
            }
        }
        else {
            if(u.l) ins(u.l, dir^1);
            else {
                u.l = ++ncnt; t[ncnt] = T;
                for(int i = 0; i < 2; i++)
                    t[ncnt].mn[i] = t[ncnt].mx[i] = t[ncnt][i];
            }
        }
        up(k);
    }
    inline LL get_dis(int k, const Node &p) {
        LL ret = 0;
        for(int i = 0; i < 2; i++) ret += max(0, p[i] - t[k].mx[i]);
        for(int i = 0; i < 2; i++) ret += max(0, t[k].mn[i] - p[i]);
        return ret;
    }
    inline void query(int x, int dir) {
        Node &u = t[x];
        int d = dis(u, T);
        int dl = INF, dr = INF;
        ans = min(ans, d);
        if(u.l) dl = get_dis(u.l, T);
        if(u.r) dr = get_dis(u.r, T);
        if(dl < dr) {
            if(dl < ans) query(u.l, dir^1);
            if(dr < ans) query(u.r, dir^1);
        }
        else {
            if(dr < ans) query(u.r, dir^1);
            if(dl < ans) query(u.l, dir^1);
        }
    }
    inline void ins(const Node &p) {
        T = p; ins(root, 0);
    }
    inline int query(const Node &p) {
        ans = INF; T = p; query(root, 0);
        return ans;
    }
} kd;
int n, m, x;
int main() {
    SF("%d%d", &n, &m);
    for(int i = 1; i <= n; i++) SF("%d%d", &A[i][0], &A[i][1]);
	kd.ncnt = n;
    kd.root = kd.build(1, n, 0, A);
    for(int i = 1; i <= m; i++) {
        int op, x, y;
        SF("%d%d%d", &op, &x, &y);
        if(op == 1) kd.ins(Node(x, y));
        else PF("%d\n", kd.query(Node(x, y)));
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值