bzoj2648

http://www.lydsy.com/JudgeOnline/problem.php?id=2648

kdtree裸题。。。

抄板子一边抄对了。。。

挺好理解的,就是说我们先找出中间的元素,然后小的放左边,大的放右边,这样我们就确定了这个点,然后维度换一下,递归建树,很像splay,其实就是把平面每次一分为二,先横着再竖着。。。

然后那个get挺神奇的,大概就是估计一下现在这个点距离下一个区域的距离?其实就是优化枚举,减少了很多重复状态。。。

#include<bits/stdc++.h>
using namespace std;
const int N = 1000010, inf = 1 << 29;
struct data {
    int l, r, d[2], min[2], max[2];
} t[N];
int n, m, root, ans, d;
bool cp(data x, data y) 
{
    if(x.d[d] != y.d[d]) return x.d[d] < y.d[d];
    return x.d[d ^ 1] < y.d[d ^ 1];
}
void update(int k)
{
    for(int i = 0; i < 2; ++i)
    {
        if(t[k].l) t[k].min[i] = min(t[k].min[i], t[t[k].l].min[i]), t[k].max[i] = max(t[k].max[i], t[t[k].l].max[i]);
        if(t[k].r) t[k].min[i] = min(t[k].min[i], t[t[k].r].min[i]), t[k].max[i] = max(t[k].max[i], t[t[k].r].max[i]);
    }
} 
int get(int k, data x)
{
    int ret = 0;
    for(int i = 0; i < 2; ++i) ret += max(t[k].min[i] - x.d[i], 0) + max(x.d[i] - t[k].max[i], 0);
    return ret;
}
int build(int l, int r, int now)
{
    d = now;
    int mid = (l + r) >> 1;
    nth_element(t + l + 1, t + mid + 1, t + r + 1, cp);
    for(int i = 0; i < 2; ++i) t[mid].min[i] = t[mid].max[i] = t[mid].d[i];
    if(l < mid) t[mid].l = build(l, mid - 1, now ^ 1);
    if(r > mid) t[mid].r = build(mid + 1, r, now ^ 1);
    update(mid); return mid;        
}
void insert(int k, int now, data x)
{
    if(x.d[now] < t[k].d[now]) 
    {
        if(t[k].l) insert(t[k].l, now ^ 1, x);
        else
        {
            t[k].l = ++n;
            for(int i = 0; i < 2; ++i) t[n].max[i] = t[n].min[i] = t[n].d[i] = x.d[i];
        }
    }
    else 
    {
        if(t[k].r) insert(t[k].r, now ^ 1, x);
        else
        {
            t[k].r = ++n;
            for(int i = 0; i < 2; ++i) t[n].max[i] = t[n].min[i] = t[n].d[i] = x.d[i];
        }
    }
    update(k);
}
void query(int k, int now, data x)
{
    int d = abs(t[k].d[0] - x.d[0]) + abs(t[k].d[1] - x.d[1]), dl = inf, dr = inf;
    ans = min(ans, d);
    if(t[k].l) dl = get(t[k].l, x);
    if(t[k].r) dr = get(t[k].r, x);
    if(dl < dr)
    {
        if(dl < ans) query(t[k].l, now ^ 1, x);
        if(dr < ans) query(t[k].r, now ^ 1, x); 
    }
    else
    {
        if(dr < ans) query(t[k].r, now ^ 1, x);
        if(dl < ans) query(t[k].l, now ^ 1, x);
    }
}
int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++i) scanf("%d%d", &t[i].d[0], &t[i].d[1]);
    root = build(1, n, 0);
    while(m--)
    {
        int opt; data x; scanf("%d%d%d", &opt, &x.d[0], &x.d[1]);
        if(opt == 1) insert(root, 0, x);
        if(opt == 2) 
        {
            ans = inf;
            query(root, 0, x);
            printf("%d\n", ans);
        }
    }
    return 0;
}
View Code

 

posted @ 2017-05-19 23:30  19992147  阅读(138)  评论(0编辑  收藏  举报