UVALive 6041 Retrenchment

不容易,kd-tree。。终于过了,wa了好久,然后快两个月没管它,今天终于过了。

题目意思很简单,然后做法就是用kd-tree找最邻近的点和次邻近的点。

有几个坑点,就是点积和叉积会爆int,然后就是我的几何模板挫了,点在线段上,由于没有判断点是否会和线段的端点重合,我一直wa。下午重新看题的时候突然想到这个点,哎。。总算过了,好开心。。

#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

#define LL long long
#define mnx 21100
#define eps 1e-8
#define mod 1000000007

struct point{
    int x, y, id;
    point( int x = 0, int y = 0 ) : x(x), y(y) {}
    point operator + ( const point &b ) const {
        return point( x + b.x, y + b.y );
    }
    point operator - ( const point &b ) const {
        return point( x - b.x, y - b.y );
    }
    LL len(){
        return (LL)x * x + (LL)y * y;
    }
    bool operator == ( const point &b ) const {
        return x == b.x && y == b.y;
    }
};
LL dot( point a, point b ){
    return (LL)a.x * b.x + (LL)a.y * b.y;
}
LL cross( point a, point b ){
    return (LL)a.x * b.y - (LL)a.y * b.x;
}
LL sqr( int x ){ return (LL)x * x; }
bool on_segment( point p, point a1, point a2 ){
    if( p == a1 || p == a2 ) return true;
    return cross( a1 - p, a2 - p ) == 0 && dot( a1 - p, a2 - p ) < 0;
}
int point_in_polygon( point p, point *poly, int n ){
    int wn = 0;
    poly[n] = poly[0];
    for( int i = 0; i < n; ++i ){
        if( on_segment( p, poly[i], poly[i+1] ) ) return 1;
        LL k = cross( poly[i+1] - poly[i], p - poly[i] );
        int d1 = poly[i].y - p.y, d2 = poly[i+1].y - p.y;
        if( k > 0 && d1 <= 0 && d2 > 0 ) wn++;
        if( k < 0 && d2 <= 0 && d1 > 0 ) wn--;
    }
    if( wn != 0 ) return 1;
    return 0;
}
bool cmpX( point a, point b ){
    return a.x<b.x || (a.x==b.x&&a.y<b.y) || (a.x==b.x&&a.y==b.y&&a.id<b.id);
}
bool cmpY( point a, point b ){
    return a.y<b.y || (a.y==b.y&&a.x<b.x) || (a.y==b.y&&a.x==b.x&&a.id<b.id);
}
bool cmp( point a, point b, bool div ){
    return div ? cmpY( a, b ) : cmpX( a, b );
}
struct node{
    point val;
    node *ls;
    node *rs;
    bool exist, div;
};
node *root;
point in[mnx], ans;
LL dis;
node *build( int l, int r, bool div ){
    if( l >= r ) return NULL;
    int m = ( l + r ) >> 1;
    nth_element( in + l, in + m, in + r, div ? cmpY : cmpX );
    node *now = new node();
    now->val = in[m], now->exist = 1, now->div = div;
    now->ls = build( l, m, div & 1 );
    now->rs = build( m+1, r, div & 1 );
    return now;
}
void search( node *a, point d ){
    if( a == NULL ) return;
    if( a->exist ){
        LL dd = ( d-a->val).len();
        if( dis>dd || (dis==dd && ans.id > a->val.id) )
            ans = a->val, dis = dd;
    }
    if( cmp( d, a->val, a->div ) ){
        search( a->ls, d );
        if( a->div ? sqr( a->val.y - d.y ) <= dis : sqr( a->val.x - d.x ) <= dis )
            search( a->rs, d );
    }
    else{
        search( a->rs, d );
        if( a->div ? sqr( a->val.y - d.y ) <= dis : sqr( a->val.x - d.x ) <= dis )
            search( a->ls, d );
    }
}
void erase( node *a, point tmp ){
    if( a->val.id == tmp.id ){
        a->exist = 0; return ;
    }
    if( cmp( tmp, a->val, a->div ) )
        erase( a->ls, tmp );
    else erase( a->rs, tmp );
}
void insert( node *a, point tmp ){
    if( a->val.id == tmp.id ){
        a->exist = 1; return ;
    }
    if( cmp( tmp, a->val, a->div ) )
        insert( a->ls, tmp );
    else insert( a->rs, tmp );
}
point p[mnx], pp[mnx];
int main(){
    freopen( "tt.txt", "r", stdin );
    int cas, kk = 1;
    scanf( "%d", &cas );
    while( cas-- ){
        printf( "Case #%d:\n", kk++ );
        int n;
        scanf( "%d", &n );
        for( int i = 1; i <= n; ++i ){
            scanf( "%d%d", &p[i].x, &p[i].y );
            p[i].id = i;
        }
        int R, B, Q;
        scanf( "%d", &R );
        for( int cnt = 1; cnt <= R; ++cnt ){
            printf( "Region %d\n", cnt );
            scanf( "%d", &B );
            for( int i = 0; i < B; ++i )
                scanf( "%d%d",&pp[i].x, &pp[i].y );
            int all = 0;
            for( int i = 1; i <= n; ++i ){
                if( point_in_polygon( p[i], pp, B ) )
                    in[all++] = p[i];
            }
            root = build( 0, all, 0 );
            scanf( "%d", &Q );
            point q;
            while( Q-- ){
                scanf( "%d%d", &q.x, &q.y );
                dis = 1000000000000000;
                search( root, q );
                point tmp = ans;
                printf( "%d ", ans.id );
                erase( root, tmp );
                dis = 1000000000000000;
                search( root, q );
                printf( "%d\n", ans.id);
                insert( root, tmp );
            }
        }
    }
    return 0;
}

  

posted @ 2014-12-16 15:48  L__J  阅读(160)  评论(0编辑  收藏  举报