题意
考虑二分答案,我们只需要判断是否存在\((a,b)\),对于任意\(i\in[1,mid]\)满足\(ax_i^2+bx_i\in[y_{1i},y_{2i}]\)。
展开可得:
\(\frac{y_{1i}}{x_i}\leqslant ax_i+b\leqslant\frac{y_{2i}}{x_i}\)
即:
\(ax_i+b-\frac{y_{1i}}{x_i}\geqslant 0\)
\(ax_i+b-\frac{y_{12}}{x_i}\leqslant 0\)
将\(a,b\)当成\(x,y\),这是两条直线,我们半平面交判断即可。
然后这题卡精度卡了我一下午,我也是真有耐心。
code:
#include<bits/stdc++.h> using namespace std; #define double long double const int maxn=100010; const double eps=1e-18; const double inf=1e12; int n,m; struct Point { double x,y; inline double len(){return sqrt(x*x+y*y);} Point operator+(const Point a)const{return (Point){x+a.x,y+a.y};} Point operator-(const Point a)const{return (Point){x-a.x,y-a.y};} Point operator*(const double k){return (Point){x*k,y*k};} Point operator/(const double k){return (Point){x/k,y/k};} double operator*(const Point a)const{return x*a.y-y*a.x;} double operator&(const Point a)const{return x*a.x+y*a.y;} }; inline int dcmp(double x) { if(fabs(x)<=eps)return 0; return x<0?-1:1; } inline Point get(Point a,Point b){return b-a;} struct Line { Point p,v;int id;double theta; bool operator<(const Line a)const { return !dcmp(theta-a.theta)?dcmp(get(p,v)*get(p,a.v))<0:dcmp(theta-a.theta)<0; } }line[maxn<<1],tmp[maxn<<1],q[maxn<<1]; inline Point getpoint(Line a,Line b) { Point p1=a.p,p2=b.p,v1=a.v,v2=b.v; v1=get(p1,v1),v2=get(p2,v2); Point u=get(p1,p2); return p2+v2*(u*v1)/(v1*v2); } inline bool check(Line a,Line b,Line c) { Point p=getpoint(a,b); return dcmp(get(c.p,c.v)*get(c.p,p))<0; } inline bool check_ans(int mid) { int l=1,r=0,cnt=0; for(int i=1;i<=m;i++) if(line[i].id<=mid&&line[i].theta!=tmp[cnt].theta)tmp[++cnt]=line[i]; for(int i=1;i<=cnt;i++) { while(l<r&&check(q[r-1],q[r],tmp[i]))r--; while(l<r&&check(q[l],q[l+1],tmp[i]))l++; q[++r]=tmp[i]; } while(l<r&&check(q[r-1],q[r],q[l]))r--; while(l<r&&check(q[l],q[l+1],q[r]))l++; return r-l+1>=3; } int main() { //freopen("test.in","r",stdin); //freopen("test.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++) { double x,y1,y2;scanf("%Lf%Lf%Lf",&x,&y1,&y2); line[++m]=(Line){(Point){0,y1/x},(Point){1,y1/x-x},i,0}; line[++m]=(Line){(Point){1,y2/x-x},(Point){0,y2/x},i,0}; } line[++m]=(Line){(Point){-inf,eps},(Point){-eps,eps},0,0}; line[++m]=(Line){(Point){-eps,eps},(Point){-eps,inf},0,0}; line[++m]=(Line){(Point){-eps,inf},(Point){-inf,inf},0,0}; line[++m]=(Line){(Point){-inf,inf},(Point){-inf,eps},0,0}; for(int i=1;i<=m;i++)line[i].theta=atan2(line[i].v.y-line[i].p.y,line[i].v.x-line[i].p.x); sort(line+1,line+m+1); int l=1,r=n,res=0; while(l<=r) { int mid=(l+r)>>1; if(check_ans(mid))res=mid,l=mid+1; else r=mid-1; } printf("%d\n",res); return 0; }
来源:https://www.cnblogs.com/nofind/p/12244720.html