BZOJ 1941 kd-tree

模板题 题意说的可能有点不清楚 一开始的点必须在给定的n个点里面

所以枚举点 然后ask最大和最小值

估价函数中 最大值的写法和最小值不同 全部取max

而最小值在估价时 如果在某个点管辖的空间里 就视为距离=0

估价函数如果写错 可能会导致wa or t

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<math.h>
#include<queue>
#include<string>
using namespace std;
#define L long long
const int INF = 999999999 ;
int n , root , cmp_d ;
struct node{
    int d[2] , Max[2] , Min[2];
    int l , r ;
}a[500050] ;
bool cmp(node a,node b){
    return ((a.d[cmp_d] < b.d[cmp_d]) || (a.d[cmp_d] == b.d[cmp_d] && a.d[!cmp_d] < b.d[!cmp_d])) ;
}
void up(int p , int k ){
    a[p].Max[0] = max(a[p].Max[0] , a[k].Max[0]);
    a[p].Max[1] = max(a[p].Max[1] , a[k].Max[1]);
    a[p].Min[0] = min(a[p].Min[0] , a[k].Min[0]);
    a[p].Min[1] = min(a[p].Min[1] , a[k].Min[1]);
}
int build(int l, int r , int  D )  {
    int mid = (l+r) >> 1 ;
    cmp_d = D;
    nth_element(a+1+l,a+1+mid,a+1+r,cmp) ;
    a[mid].Max[0] = a[mid].Min[0] = a[mid].d[0];
    a[mid].Max[1] = a[mid].Min[1] = a[mid].d[1];
    if(l != mid)
        a[mid].l = build(l,mid-1,D^1);
    else a[mid].l = 0 ;
    if(r != mid)
        a[mid].r = build(mid+1,r,D^1);
    else a[mid].r = 0 ;
    if(a[mid].l)up(mid,a[mid].l);
    if(a[mid].r)up(mid,a[mid].r);
    return mid ;
}
int ans1 , ans2 ;
int x, y ;
int getMaxdis(int p) {
    int res = 0 ;
    res += max(max(x - a[p].Max[0] , a[p].Max[0] - x) , max(x - a[p].Min[0] , a[p].Min[0] - x)) ;
    res += max(max(y - a[p].Max[1] , a[p].Max[1] - y) , max(y - a[p].Min[1] , a[p].Min[1] - y)) ;
    return res ;
}
void query_Max(int p) {
    int d0 ;
    int dl,dr ;
    d0 = abs(x - a[p].d[0]) + abs(y - a[p].d[1]) ;
    if(d0 != 0) {
        ans2 = max(ans2 , d0) ;
    }
    if(a[p].l)
        dl = getMaxdis(a[p].l) ;
    else dl = -INF ;
    if(a[p].r)
        dr = getMaxdis(a[p].r) ;
    else dr = -INF ;
    if(dl > dr) {
        if(dl > ans2)query_Max(a[p].l) ;
        if(dr > ans2)query_Max(a[p].r) ;
    }
    else {
        if(dr > ans2)query_Max(a[p].r) ;
        if(dl > ans2)query_Max(a[p].l) ;
    }
}
int getMindis(int p) {
    int res = 0 ;
    if(x > a[p].Max[0]) res += x - a[p].Max[0] ;
    if(x < a[p].Min[0]) res += a[p].Min[0] - x ;
    if(y > a[p].Max[1]) res += y - a[p].Max[1] ;
    if(y < a[p].Min[1]) res += a[p].Min[1] - y ;
    return res ;
}
void query_Min(int p) {
    int d0 , dl , dr ;
    d0 = abs(a[p].d[0] - x) + abs(a[p].d[1] - y) ;
    if(d0 != 0) {
        ans1 = min(d0 , ans1) ;
    }
    if(a[p].l)
        dl = getMindis(a[p].l) ;
    else dl = INF ;
    if(a[p].r)
        dr = getMindis(a[p].r) ;
    else dr = INF ;
    if(dl < dr) {
        if(dl < ans1)query_Min(a[p].l) ;
        if(dr < ans1)query_Min(a[p].r) ;
    }
    else {
        if(dr < ans1)query_Min(a[p].r) ;
        if(dl < ans1)query_Min(a[p].l) ;
    }
}
int main(){
    int n ;
    scanf("%d",&n);
    for(int i = 1; i <= n ; i ++ ){
        scanf("%d%d",&a[i].d[0],&a[i].d[1]) ;
    }
    root = build(1,n,0) ;
    int ans = INF ;
    for(int i = 1; i <= n ; i ++ ){
        ans1 = INF , ans2 = -INF ;
        x = a[i].d[0] , y = a[i].d[1] ;
        query_Max(root) ;
        query_Min(root) ;
        ans = min(ans , ans2 - ans1) ;
    }
    printf("%d\n",ans) ;
}

  

 

posted @ 2017-01-26 15:28  天翎月  阅读(156)  评论(0编辑  收藏  举报