题意:给你一个x1和x2,然后给你n (2 ≤ n ≤ 100 000)个k和b,就得到n个y=kx+b的线性方程,
然后让你找出两两方程交点是不是在x1和x2的里面。
看图:第一组测试数据的图
4 1 2 1 2 1 0 0 1 0 2x1=1,x2=2;
y=x+2;
y=x;
y=1;
y=2;
图上可以清楚的看到,没有交点在x1和x2之间。
读完题,想了一下我就开始自暴自弃了,我觉得太难了,暴力肯定不可以的,我当时都放弃了。
后来我想到了当时求最长不递增子序列用二分的模板题就是一个类似这个图的形式,我就发现这个题的规律了,
对于所有的方程我是知道的,方程就在对x1带入可以得到一个y1,x2带入可以得到一个y2,n个方程带入进去就可以得到2*n个y。然后把通过x1求到的y排序,然后去找通过x2求到的y的规律就可以。具体代码中看吧。(后来我发现我真的太傻)
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
double num[100005];
struct node
{
double aa;
double bb;
} e[100005];
double k[100005];
double b[100005];
double cmp(node s1,node s2)
{
if(s1.aa==s2.aa)//不写这句话就是错的,因为交点在x1和x2上不算
return s1.bb<s2.bb;
return s1.aa<s2.aa;
}
int Search(double n,int l,int h)
{
int mid;
while(l<=h)
{
mid=(l+h)/2;
if(num[mid-1]<=n&&num[mid]>n)
{
return mid;
}
if(num[mid]>n)
h=mid-1;
else
l=mid+1;
}
return 0;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
double x1,x2;
scanf("%lf%lf",&x1,&x2);
for(int i=0; i<n; i++)
{
scanf("%lf%lf",&k[i],&b[i]);
e[i].aa=k[i]*x1+b[i];//通过x1求到一个y存在aa中
e[i].bb=k[i]*x2+b[i];//通过x2求到一个y存在bb中
}
sort(e,e+n,cmp);
for(int i=0; i<n; i++)
{
num[i+1]=e[i].bb;
}
//二分求解最长不下降子序列(当复习吧,后面解释我二的地方)
int id;
int idx;
for(int i=2,j=1; i<=n; i++)
{
if(num[i]>=num[j])
{
num[++j]=num[i];
}
else
{
idx=Search(num[i],1,j);
num[idx]=num[i];
}
id=j;
}
if(id==n)//如果是n个,那么就没有交点在内部
printf("NO\n");
else
printf("YES\n");
}
}
我为啥说我二,只有我才这样写,其实后面根本用不到求最长不下降子序列,只需要看后面的数是不是比前面的大就可以了,如果有一个数比前面的小,那么就直接结束,打出YES。开一个标记变量既可。 思维太局限了。