博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ 2732 射箭(半平面交)
阅读量:6647 次
发布时间:2019-06-25

本文共 1580 字,大约阅读时间需要 5 分钟。

题目链接:

题意:给出n条第一象限内的竖直线段。求一个最大的K,使得某条经过原点的抛物线穿过前K条线段。

 

思路:设线段为(x,y1,y2),设抛物线为y=ax^2+b^x,那么有:y1<=ax^2+bx<=y2。据此可得到穿过该线段的抛物线参数a和b的两个方程,这两个方程是线性的。因此,可以半平面交,直到半平面内的点构不成多边形。

 

struct point
{
    double x,y;
    
    point(){}
    point(double _x,double _y)
    {
        x=_x;
        y=_y;
    }
    
    point operator+(point a)
    {
        return point(x+a.x,y+a.y);
    }
    
    point operator-(point a)
    {
        return point(x-a.x,y-a.y);
    }
    
    double operator*(point a)
    {
        return x*a.y-y*a.x;
    }
    
    point operator*(double t)
    {
        return point(x*t,y*t);
    }
    
    point operator/(double t)
    {
        return point(x/t,y/t);
    }
};
point a[2][N];
int n,cnt[2],pre,cur;
int sgn(double x)
{
    if(x>EPS) return 1;
    if(x<-EPS) return -1;
    return 0; 
}
int getDir(point p,point q,point a)
{
    double t=(q-p)*(a-p);
    return sgn(t)>=0;
}
void add(point p)
{
    a[cur][cnt[cur]++]=p;
}
point cross(point a,point b,point p,point q)
{
    double s1=(a-p)*(b-p);
    double s2=(b-q)*(a-q);
    double t=s1+s2;
    return (p*s2+q*s1)/(s1+s2);
}
void cut(double k,double b,int isLeft)
{
    point p=point(0,b),q=point(100,100*k+b);
    cnt[cur]=0;
    int i;
    a[pre][cnt[pre]]=a[pre][0];
    point p1,q1;
    int x,y;
    FOR0(i,cnt[pre])
    {
        p1=a[pre][i];
        q1=a[pre][i+1];
        x=getDir(p,q,p1)==isLeft;
        y=getDir(p,q,q1)==isLeft;
        if(x&&y) add(p1);
        else if(x) add(p1),add(cross(p,q,p1,q1));
        else if(y) add(cross(p,q,p1,q1));
    }
}
int main()
{
    RD(n);
    pre=0,cur=1;
    a[pre][0]=point(inf,0);
    a[pre][1]=point(inf,inf);
    a[pre][2]=point(-inf,inf);
    a[pre][3]=point(-inf,0);
    cnt[pre]=4;
    double x,y1,y2;
    int ans,i,flag=0;
    FOR1(i,n)
    {
        RD(x,y1,y2);
        if(flag) continue;
        ans=i;
        cut(-x,y1/x,1); swap(pre,cur);
        cut(-x,y2/x,0); swap(pre,cur);
        if(cnt[pre]<=2) ans=i-1,flag=1;
    }
    PR(ans);
}

你可能感兴趣的文章
vs2010开发安卓系统
查看>>
Splunk Forward简单部署_Win
查看>>
Oracle 双机热备:Oracle dataguard 和Oracle rac的区别和联系
查看>>
如何只显示不同字段值的行?
查看>>
挂载ISO文件
查看>>
DataGridView 经典用法总结(一)
查看>>
Java并发显式锁和显式条件队列
查看>>
云OS可国产替代
查看>>
try-catch 能否监听多线程中的错误?
查看>>
Android使用Token 实现单点登录
查看>>
模拟器可以,但是真机却不行
查看>>
CSS: hover选择器的使用
查看>>
Java消息服务
查看>>
Grid列拖拽、列选择、显示行号
查看>>
自定义的allocator
查看>>
浅谈CSRF漏洞
查看>>
JS----基本数据类型
查看>>
明天考前突击
查看>>
Android中的Handler的机制与用法详解
查看>>
【算法学习笔记】18.暴力求解法06 隐式图搜索2 八数码问题 未启发
查看>>