計算幾何(一道題) Geometry

計算幾何

題意描述

花花對計算幾何有着濃厚的興趣。他經常對着平面直角座標系發呆,思考一些有趣的問題。今天,他想到了一個十分有意思的題目:

首先,花花會在 x 軸正半軸和 y 軸正半軸分別挑選 n 個點。隨後,他將 x 軸的點與 y 軸的點一一連接,形成 n 條線段,並保證任意兩條線段不相交。花花確定這種連接方式有且僅有一種。最後,花花會給出 m 個詢問。對於每個詢問,將會給定一個點 P(xp, yp),問線段OP(O 爲座標原點)與 n 條線段會產生多少個交點?

輸入格式

第 1 行包含一個正整數 n,表示線段的數量;
第 2 行包含 n 個正整數,表示花花在 x 軸選取的點的橫座標;
第 3 行包含 n 個正整數,表示花花在 y 軸選取的點的縱座標;
第 4 行包含一個正整數 m,表示詢問數量;
隨後 m 行,每行包含兩個正整數 xp 和 yp,表示詢問中給定的點的橫、縱座標。

輸出格式

共 m 行,每行包含一個非負整數,表示你對這條詢問給出的答案。

樣例輸入

3
4 5 3
3 5 4
2
1 1
3 3

樣例輸出

0
3

樣例解釋

3 條線段分別爲:(3, 0) − (0, 3)、(4, 0) − (0, 4)、(5, 0) − (0, 5)
(0, 0) − (1, 1) 不與他們有交點,答案爲 0。
(0, 0) − (3, 3) 與三條線段均有交點,答案爲 3。

3.7 數據規模與約定
• 對於 40% 的數據:n,m10
• 另有 20% 的數據:n,m100
• 另有 20% 的數據:n,m1000
• 對於 100% 的數據:n,m105,1x,y<231


送分題,貼出來主要是應用了二分的思想,由於情況具有單調性,用二分可優化時間複雜度


#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

const int MAXN=1e5;
int n,m;

struct L{double k;int b,l,r;} l[MAXN+1];
bool isCross(L f,L s)
{
    if(f.k==s.k) return false;
    if(f.k==0) {if(s.b>=f.l&&s.b<=f.r) return true; return false;}
    if(s.k==0) {if(f.b>=s.l&&f.b<=s.r) return true; return false;}
    double x=(double)(s.b-f.b)/(f.k-s.k);
    if(x>=f.l&&x<=f.r&&x>=s.l&&x<=s.r) return true;
    return false;
}
int inx[MAXN+1],iny[MAXN+1];

int main()
{
    freopen("geometry.in","r",stdin);
    freopen("geometry.out","w",stdout);
    int i,j;
    scanf("%d",&n);
    for(i=1;i<=n;i++) scanf("%d",&inx[i]);
    for(i=1;i<=n;i++) scanf("%d",&iny[i]);
    sort(inx+1,inx+n+1);sort(iny+1,iny+n+1);
    for(i=1;i<=n;i++)
    {
        int x=inx[i],y=iny[i];
        if(x==0) l[i]=(L){0,0,y>0?0:y,y>0?y:0};
        else l[i]=(L){(double)y*(-1.0)/x,y,x>0?0:x,x>0?x:0};
    }
    scanf("%d",&m);
    while(m--)
    {
        int ans=0;
        int x,y;
        scanf("%d%d",&x,&y);
        L rl;
        if(x==0) rl=(L){0,0,y>0?0:y,y>0?y:0};
        else rl=(L){(double)y/x,0,x>0?0:x,x>0?x:0};
        int mina=0,maxa=n;
        while(mina<maxa)
        {
            int mid=(mina+maxa+1)>>1;
            if(isCross(l[mid],rl)) mina=mid;
            else maxa=mid-1;
        }
        printf("%d\n",mina);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章