• 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:
    ", 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
    ", 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
    ", ans.id);
                    insert( root, tmp );
                }
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    (转)正则表达式与Python(RE)模块
    (转)【面试】【MySQL常见问题总结】【03】
    (转)MySQL性能调优my.cnf详解
    (转)python logging模块
    (转)python collections模块详解
    mysql故障总结
    rocksdb 编译安装 日志
    c++11 gcc4.8.x安装
    Install ssdb-rocks on CentOS 6
    在Shell里面判断字符串是否为空
  • 原文地址:https://www.cnblogs.com/LJ-blog/p/4167272.html
Copyright © 2020-2023  润新知