• poj2318(叉积判断点在直线左右+二分)


    题目链接:https://vjudge.net/problem/POJ-2318

    题意:有n条线将矩形分成n+1块,m个点落在矩形内,求每一块点的个数。

    思路:

      最近开始肝计算几何,之前的几何题基本处于挂机状态,但听别人说几何题不会太难,所以打算把几何给过了。

      先引入叉积的一个重要性质,O为原点:

        OP^OQ>0 : P在Q的顺时针方向。

        OP^OQ<0 : P在Q的逆时针方向。

        OP^OQ=0 : O,P,Q共线。

      那么我们就可以利用该性质判断一个点P在直线AB的左侧当且仅当:PA^PB<0。

      再发现可以用二分查找第一条满足点在直线左侧的直线即可,其单调性显然可知。

    AC code:

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    
    const int maxn=5005;
    int n,m,x1,y1,x2,y2,ans[maxn],flag=1;
    
    struct Point{
        int x,y;
        Point(){}
        Point(int xx,int yy):x(xx),y(yy){}
        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);
        }
        int operator * (const Point& b)const{
            return x*b.x+y*b.y;
        }
        int operator ^ (const Point& b)const{
            return x*b.y-b.x*y;
        }
    };
    
    struct Line{
        Point s,e;
        Line(){};
        Line(Point ss,Point ee){
            s=ss,e=ee;
        }
    }line[maxn];
    
    int check(int x,int y,int m){
        Point pt=Point(x,y);
        return (line[m].s-pt)^(line[m].e-pt);
    }
    
    int main(){
        while(scanf("%d",&n),n){
            if(flag) flag=0;
            else printf("
    ");
            scanf("%d%d%d%d%d",&m,&x1,&y1,&x2,&y2);
            for(int i=0;i<=n;++i)
                ans[i]=0;
            for(int i=0;i<n;++i){
                int u,l;
                scanf("%d%d",&u,&l);
                line[i]=Line(Point(u,y1),Point(l,y2));
            }
            line[n]=Line(Point(x2,y1),Point(x2,y2));
            while(m--){
                int x,y;
                scanf("%d%d",&x,&y);
                Point pt=Point(x,y);
                int l=0,r=n,mid;
                while(l<=r){
                    mid=(l+r)>>1;
                    if(check(x,y,mid)<=0) r=mid-1;
                    else l=mid+1;
                }
                ++ans[l];
            }
            for(int i=0;i<=n;++i)
                printf("%d: %d
    ",i,ans[i]);
        }
    }
  • 相关阅读:
    [JOISC2017]細長い屋敷
    Gym102471C Dirichlet k-th root
    CF1264F Beautiful Fibonacci Problem
    Luogu P4619 [SDOI2018]旧试题
    AGC001F Wide Swap
    BZOJ4289 [PA2012]Tax
    Luogu P4366 [Code+#4]最短路
    Luogu P1407 [国家集训队]稳定婚姻
    CF1023F Mobile Phone Network
    BZOJ3563 DZY Loves Chinese
  • 原文地址:https://www.cnblogs.com/FrankChen831X/p/11471321.html
Copyright © 2020-2023  润新知