計算幾何
題意描述
花花對計算幾何有着濃厚的興趣。他經常對着平面直角座標系發呆,思考一些有趣的問題。今天,他想到了一個十分有意思的題目:
首先,花花會在 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% 的數據:
• 另有 20% 的數據:
• 另有 20% 的數據:
• 對於 100% 的數據:
送分題,貼出來主要是應用了二分的思想,由於情況具有單調性,用二分可優化時間複雜度
#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;
}