1.题目描述:
The teacher gave Anton a large geometry homework, but he didn't do it (as usual) as he participated in a regular round on Codeforces. In the task he was given a set of n lines defined by the equations y = ki·x + bi. It was necessary to determine whether there is at least one point of intersection of two of these lines, that lays strictly inside the strip between x1 < x2. In other words, is it true that there are1 ≤ i < j ≤ n and x', y', such that:
- y' = ki * x' + bi, that is, point (x', y') belongs to the line number i;
- y' = kj * x' + bj, that is, point (x', y') belongs to the line number j;
- x1 < x' < x2, that is, point (x', y') lies inside the strip bounded by x1 < x2.
You can't leave Anton in trouble, can you? Write a program that solves the given task.
The first line of the input contains an integer n (2 ≤ n ≤ 100 000) — the number of lines in the task given to Anton. The second line contains integers x1 and x2 ( - 1 000 000 ≤ x1 < x2 ≤ 1 000 000) defining the strip inside which you need to find a point of intersection of at least two lines.
The following n lines contain integers ki, bi ( - 1 000 000 ≤ ki, bi ≤ 1 000 000) — the descriptions of the lines. It is guaranteed that all lines are pairwise distinct, that is, for any two i ≠ j it is true that either ki ≠ kj, or bi ≠ bj.
Print "Yes" (without quotes), if there is at least one intersection of two distinct lines, located strictly inside the strip. Otherwise print "No" (without quotes).
4 1 2 1 2 1 0 0 1 0 2
NO
2 1 3 1 0 -1 3
YES
2 1 3 1 0 0 2
YES
2 1 3 1 0 0 3
NO
In the first sample there are intersections located on the border of the strip, but there are no intersections located strictly inside it.
你n条直线,问你在[x1, x2]的开区间里面存不存在至少一个交点。
3.解题思路:
其实这道也出现在新生赛上面,然后我当时用的叉乘判断直线相交A了,但是cf被卡了,估计是精度问题
根据直线的k 和 b求出与x = x1 和 x = x2的交点坐标,分别用lv和rv来记录。
这样只要存在i和j(i != j)满足num[i].lv > num[j].lv && num[i].rv < num[j].rv就可以判定存在交点。
关键在于如何高效的查找。我们可以先按lv升序排列,再按rv升序排列,然后依次比较。
分析比较过程:(数组下标从1-n)首先取一个k = 1,然后遍历i(2 <= i <= n).
我们来比较num[k]和num[i]的lv、rv
(1) 满足上面的判定条件,存在交点;
(2) num[k].lv == num[i].lv,为了最大概率找到交点,我们取rv值较小的代替k向下比较,这样k = i;
(3) num[k].rv > num[i].rv,同(2),k = i;
(4) num[k].rv == num[i].rv,同(2), k = i;
上面的后三种处理可以放在一起。这样查询只需要O(n)的时间复杂度。
4.AC代码:
#include <algorithm>
#include <stdio.h>
#include <cmath>
#define maxn 2010000
using namespace std;
typedef long long ll;
ll x1, x2, n;
int flag;
struct line
{
ll ya, yb;
}l[maxn];
int cmp(line a, line b)
{
if (a.ya != b.ya)
return a.ya < b.ya;
return a.yb < b.yb;
}
int main()
{
while (scanf("%lld", &n) != EOF)
{
flag = 0;
scanf("%lld%lld", &x1, &x2);
for (ll i = 0; i < n; i++)
{
ll k, b;
scanf("%lld%lld", &k, &b);
l[i].ya = k * x1 + b;
l[i].yb = k * x2 + b;
}
sort(l, l + n, cmp);
ll cnt = 0;
for (ll i = 1; i < n; i++)
{
if (l[i].ya > l[cnt].ya && l[i].yb < l[cnt].yb)
{
flag = 1;
break;
}
cnt++;
}
if (flag)
puts("YES");
else
puts("NO");
}
return 0;
}