首页 > 代码库 > UVALive 6041 Retrenchment

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 1000000007struct 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;}

  

UVALive 6041 Retrenchment