BZOJ2732: [HNOI2012] Archery - Problem Solving

https://www.lydsy.com/JudgeOnline/problem.php?id=2732

https://www.luogu.org/problemnew/show/P3222#sub

Momo is playing a two-dimensional archery game recently. As shown in Figure 1 below, the x-axis in this game is on the ground, and there are some vertical line segments in the first quadrant as targets. Any two targets have no common part, nor will touch the axes.

Momo controls an archer located at (0,0) and can shoot arrows of light with penetrating power at any angle from 0 to 90 degrees (excluding 0 and 90 degrees). Since there is no air resistance in the game, and the arrow of light has no arrow body, the trajectory of the arrow will be a standard parabola, and all targets passed by the trajectory are considered to have been hit by Momo, including those targets that only have their endpoints hit. .

There are many modes in this game, among which Momo's favorite is the pass mode.

In the pass-through mode, there is only one target in the first stage. If you hit this target, you can enter the second stage. At this time, another target will appear on the basis of the first stage. If you can hit both targets with one arrow, you can enter the second stage. In the third level, a third target will appear. And so on, every time you pass a level, a new target will appear. In the K level, you must hit all K targets in the previous K level with one arrow to enter the K+1 level, otherwise the game ends.

Momo spent a lot of time on this game, but she could only play the seventh level "Seven Stars" at most, which made her very confused. So she managed to get the position of the target that appeared in each level and wanted you to tell her how many levels can be passed at most

Let me remind you in the front row that doing this question is killing yourself.

Divide the answer, then you can know how many vertical lines to choose, and then judge whether there is a quadratic function that passes through all the vertical lines.

Quadratic function to judge the intersection with a bunch of vertical lines? Enumerate two points to form a quadratic function and then judge? Obviously TLE.

Considering y=ax^2+bx, if we consider whether there are valid a and b, can it be written better.

So we have y1/x<=ax+b<=y2/x, so we have:

-xa+y1/x<=b;

-xa+y2/x>=b;

Much like linear programming , it encloses an area.

Then we mix all such expressions together to find the intersection of the lower half plane!

But obviously a<0,b>0, then we need to add two sides in addition to the outer border.

In addition, if the feasible region is a point or a line segment, it is also possible to expand the target up and down a little in order to avoid misjudgment.

In addition, this question is serious about the accuracy of the problem. If you open a small meeting WA, you will open a large meeting TLE.

I've never seen a question with such a stuttering accuracy!

Why are you so proficient in the accuracy of the card, how many times have you carded the accuracy!

#include<cstdio>
#include<queue>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long double dl;
const dl eps=1e-15;
const dl INF=1e10;
const int N=100020;
struct point{dl x,y;};
struct line{
    point a,b;
    dl angle;int id;
    line(){}
    line(dl x1,dl y1,dl x2,dl y2){
    ax =x1;ay=y1;bx=x2;by= y2;
    angle =atan2(by-ay,bx- ax);
    }
}e[N*2],t[N*2],q[N*2];
int n,m;
inline point getmag(point a,point b){
    point s;
    s.x=b.x-a.x;s.y=b.y-a.y;
    return s;
}
inline dl multiX(point a,point b){
    return a.x*b.y-b.x*a.y;
}
inline bool cmp(line a,line b){
    if(fabs(a.angle-b.angle)<eps)
    return multiX(getmag(b.a,a.a),getmag(b.a,b.b))<=eps;
    return a.angle<b.angle;
}
inline point intersection(line a,line b){
    dl k1,k2,t;
    k1=multiX(getmag(a.a,b.a),getmag(a.a,a.b));
    k2=multiX(getmag(a.a,a.b),getmag(a.a,b.b));
    t=k1/(k1+k2);
    point s;
    s.x=b.a.x+(b.b.x-b.a.x)*t;
    s.y=b.a.y+(b.b.y-b.a.y)*t;
    return s;
}
inline bool jud(line a,line b,line c){
    point p=intersection(a,b);
    return multiX(getmag(c.a,p),getmag(c.a,c.b))<=eps;
}
bool pan(int k){
    int l=1,r=0,cnt=0;
    for(int i=1;i<=m;i++){
    if(e[i].id<=k&&(!cnt||e[i].angle>t[cnt].angle))t[++cnt]=e[i];
    }
    q[++r]=t[1];q[++r]=t[2];
    for(int i=3;i<=cnt;i++){
    while(l<r&&!jud(q[r],q[r-1],t[i]))r--;
    while(l<r&&!jud(q[l],q[l+1],t[i]))l++;
    q[++r]=t[i];
    }
    while(l<r&&!jud(q[r],q[r-1],q[l]))r--;
    while(l<r&&!jud(q[l],q[l+1],q[r]))l++;
    return r-l+1>2;
}
int main(){
    scanf("%d",&n);
    e[++m]=line(0,0,0,1),e[m].id=0;
    e[++m]=line(0,0,1,0),e[m].id=0;
    e[++m]=line(INF,INF,-INF,INF),e[m].id=0;
    e[++m]=line(-INF,INF,-INF,-INF),e[m].id=0;
    for(int i=1;i<=n;i++){
        dl a,y1,y2;
        scanf("%Lf%Lf%Lf",&a,&y1,&y2);y1-=eps;y2+=eps;
    dl b=y1/a,c=y2/a;
    e[++m]=line(0,b,1,b-a),e[m].id=i;
    e[++m]=line(1,c-a,0,c),e[m].id=i;
    }
    sort(e+1,e+m+1,cmp);
    int l=1,r=n;
    while(l<r){
        int mid=(l+r+1)>>1;
        if(pan(mid))l=mid;
        else r=mid-1;
    }
    printf("%d\n",l);
    return 0;
}

+++++++++++++++++++++++++++++++++++++++++++

+ Author of this article: luyouqi233. +

+Welcome to my blog: http://www.cnblogs.com/luyouqi233/  +

+++++++++++++++++++++++++++++++++++++++++++

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325140699&siteId=291194637