K-D Tree 模板

洛谷P2479 [SDOI2010] 捉迷藏

#include <bits/stdc++.h>

#define Min(_A, _B) (_A < _B ? _A : _B)
#define Max(_A, _B) (_A > _B ? _A : _B)
#define Abs(_A) (_A > 0 ? _A : -(_A))

struct pair{ int x, y; } a[500010];
struct KD_Tree{ int xmin, xmax, ymin, ymax, myx, myy; KD_Tree *l, *r; } b[1 << 22], *rt = b; int tot;
bool vis[1 << 22];
int N, lim;
bool cmp1(const pair &i, const pair &j){ return i.x < j.x; }
bool cmp2(const pair &i, const pair &j){ return i.y < j.y; }
void Build(KD_Tree *&u, int Ls, int Rs, int s)
{
    u = b + ++tot; *u = b[0];
    int Mid = Ls + Rs >> 1;
    if(s & 1) std::nth_element(a + Ls, a + Mid, a + Rs + 1, cmp1);
    else std::nth_element(a + Ls, a + Mid, a + Rs + 1, cmp2);
    if(Ls < Mid) Build(u->l, Ls, Mid - 1, s ^ 1);
    if(Rs > Mid) Build(u->r, Mid + 1, Rs, s ^ 1);
    u->myx = a[Mid].x; u->myy = a[Mid].y;
    u->xmin = Min(u->l->xmin, u->r->xmin);
    u->xmax = Max(u->l->xmax, u->r->xmax);
    u->xmin = Min(u->xmin, u->myx);
    u->xmax = Max(u->xmax, u->myx);
    u->ymin = Min(u->l->ymin, u->r->ymin);
    u->ymax = Max(u->l->ymax, u->r->ymax);  
    u->ymin = Min(u->ymin, u->myy);
    u->ymax = Max(u->ymax, u->myy);
}
int Get_Min(KD_Tree *u, int p)
{
    int dis = 0;
    if(u->xmin >= a[p].x) dis += u->xmin - a[p].x;
    if(u->xmax <= a[p].x) dis += a[p].x - u->xmax;
    if(u->ymin >= a[p].y) dis += u->ymin - a[p].y;
    if(u->ymax <= a[p].y) dis += a[p].y - u->ymax;
    return dis;
}
int Get_Max(KD_Tree *u, int p)
{
    int dis = 0;
    dis += Max(Abs(a[p].x - u->xmin), Abs(u->xmax - a[p].x));
    dis += Max(Abs(a[p].y - u->ymin), Abs(u->ymax - a[p].y));
    return dis;
}
void Query_Min(KD_Tree *u, int p)
{
    int t = Abs(a[p].x - u->myx) + Abs(a[p].y - u->myy);
    if(t)   lim = Min(lim, t);
    if(lim <= Get_Min(u, p)) return ;
    if(u->l != b && u->r != b && Get_Min(u->l, p) > Get_Min(u->r, p)) std::swap(u->l, u->r);
    if(u->l != b) Query_Min(u->l, p);
    if(u->r != b) Query_Min(u->r, p);
}
void Query_Max(KD_Tree *u, int p)
{
    int t = Abs(a[p].x - u->myx) + Abs(a[p].y - u->myy);
    if(t) lim = Max(lim, t);
    if(lim >= Get_Max(u, p)) return ;
    if(u->l != b && u->r != b && Get_Max(u->l, p) < Get_Max(u->r, p)) std::swap(u->l, u->r);
    if(u->l != b) Query_Max(u->l, p);
    if(u->r != b) Query_Max(u->r, p);
}
int main()
{
    b[0] = (KD_Tree){2147483647, 0, 2147483647, 0, 0, 0, b, b};
    scanf("%d", &N);
    for(int i = 1; i <= N; ++i) scanf("%d %d", &a[i].x, &a[i].y);
    Build(rt, 1, N, 0);
    int ans = 2147483647;
    for(int i = 1; i <= N; ++i)
    {
        int tmp = 0;
        lim = 2147483647; Query_Min(rt, i); tmp -= lim;
        lim = 0; Query_Max(rt, i); tmp += lim;
        ans = Min(tmp, ans);
    }
    printf("%d\n", ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值