codeforces 593B

题意:给你一个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 2
x1=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。开一个标记变量既可。  思维太局限了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值