平面直接坐标系线段相交问题(小Q(钟神)的问题)
【问题描述】
小 Q 对计算几何有着浓厚的兴趣。他经常对着平面直角坐标系发呆,思考
一些有趣的问题。今天,他想到了一个十分有意思的题目:
首先,小 Q 会在?轴正半轴和?轴正半轴分别挑选?个点。随后,他将?轴的
点与?轴的点一一连接,形成?条线段,并保证任意两条线段不相交。小 Q 确定
这种连接方式有且仅有一种。最后,小 Q 会给出?个询问。对于每个询问,将会
给定一个点?(? ? ,? ? ),请回答线段 OP 与?条线段会产生多少个交点?
小 Q 找到了正在钻研数据结构的你,希望你可以帮他解决这道难题。
【输入格式】
第1一个正整数?,表示线段的数量;
第2横 第3行包含?个正整数,表示小 Q 在?轴选取的点的纵坐标;
第 4 行包含一个正整数?,表示询问数量;
随后?行,每行包含两个正整数? ? ,? ? ,表示询问中给定的点的横、纵坐标。
【输出格式】
共?行,每行包含一个非负整数,表示你对这条询问给出的答案。
【样例输入】
3
4 5 3
3 5 4
2
1 1
3 3
【样例输出】
0
3
【样例解释】
然后塔里啥都没有,除了钟神。
【数据规模与约定】
50%的数据,1 ≤ ?,?,≤ 2 × 10 3 。
对于100%的数据,1 ≤ ?,? ≤ 2× 10 5 ,坐标范围≤ 10 8 。
思路:
给你很多很多的横坐标和纵坐标,然后告诉我们这全能够连成线段;
当时做的时候,一看直接蒙圈,写了个tle自动机就睡觉去了,现在一看原来这么简单;
因为连成的线段互不相交
所以这些线段与x轴y轴的交点一定有单调性(自己画个图马上就明白)
所以先将这些横坐标纵坐标排序
然后
跟据已经排好序的x,和下标相同的y来组成线段
求出线段所在直线的k,b(y==x*k+b);
接下来就是二分答案;
二分线段下标
如果将当前点的坐标带入当前线段直线度的解析式所得的值大于当前点
则向前二分
如果小于当前点的话
则记录答案,向后二分
最后输出答案
来,上代码:
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; struct node { double k,b; }; struct node edge[200005]; double a[200005],b[200005]; int n,m; int check(double x,double y)//check才是二分的精髓 { double cur; int mid,l=1,r=n,ans=0; while(l<=r) { mid=(l+r)/2; cur=edge[mid].k*x+edge[mid].b; if(cur<=y) ans=mid,l=mid+1; else r=mid-1; } return ans; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%llf",&a[i]); for(int i=1;i<=n;i++) scanf("%llf",&b[i]); sort(a+1,a+n+1); sort(b+1,b+n+1); for(int i=1;i<=n;i++) edge[i].b=b[i],edge[i].k=-1*edge[i].b/a[i]; scanf("%d",&m); double px,py; for(double i=1;i<=m;i++) { scanf("%llf%llf",&px,&py); printf("%d\n",check(px,py)); } return 0; }