1 条题解
-
0
自动搬运
来自洛谷,原作者为

p_b_p_b
*const int brain=NULL;搬运于
2025-08-24 21:46:20,当前版本为作者最后更新于2019-01-24 20:15:59,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
本题最好的一篇题解的图片似乎咕咕咕了,那我来补一篇吧,顺便发个计算几何板子。
首先你画画图,发现一个性质:从上往下看能看到的图像一定是一个下凸的图像,像这样:

至于为什么嘛……画下图就出来了。
再观察一下:从左往右,斜率递增。
那么做法就很明显了:
· 直线以斜率为第一关键字,截距为第二关键字排序;
· 维护一个单调栈记录当前能看见的直线编号;
· 每次加入一条直线就把栈顶被覆盖的直线丢掉(用直线交点判一下就好了)。
· 输出答案。
我的代码巨长无比,因为有其他计算几何的模板。推荐一个挺好的学习笔记:https://www.cnblogs.com/candy99/p/6360536.html 。Candy?太神仙了。(然而那里面的线段相交似乎挂了)
代码:
#include<bits/stdc++.h> namespace my_std{ using namespace std; #define pii pair<int,int> #define fir first #define sec second #define MP make_pair #define rep(i,x,y) for (int i=(x);i<=(y);i++) #define drep(i,x,y) for (int i=(x);i>=(y);i--) #define go(x) for (int i=head[x];i;i=edge[i].nxt) #define sz 50505 typedef long long ll; template<typename T> inline void read(T& t) { t=0;char f=0,ch=getchar(); double d=0.1; while(ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar(); while(ch<='9'&&ch>='0') t=t*10+ch-48,ch=getchar(); if(ch=='.') { ch=getchar(); while(ch<='9'&&ch>='0') t+=d*(ch^48),d*=0.1,ch=getchar(); } t=(f?-t:t); } template<typename T,typename... Args> inline void read(T& t,Args&... args){read(t); read(args...);} void file() { #ifndef ONLINE_JUDGE freopen("a.txt","r",stdin); #endif } // inline ll mul(ll a,ll b){ll d=(ll)(a*(double)b/mod+0.5);ll ret=a*b-d*mod;if (ret<0) ret+=mod;return ret;} } using namespace my_std; #define I inline typedef double db; const db eps=1e-8; I int dcmp(db x){return fabs(x)<=eps?0:(x>0?1:-1);} struct Vector { db x,y; Vector(db xx=0,db yy=0){x=xx,y=yy;} I const Vector operator + (const Vector &a) const {return Vector(x+a.x,y+a.y);} I const Vector operator - (const Vector &a) const {return Vector(x-a.x,y-a.y);} I const Vector operator * (const db &a) const {return Vector(x*a,y*a);} I const Vector operator / (const db &a) const {return Vector(x/a,y/a);} I const bool operator < (const Vector &a) const {return dcmp(x-a.x)==0?dcmp(y-a.y)<0:dcmp(x-a.x)<0;} I const bool operator == (const Vector &a) const {return dcmp(x-a.x)==0&&dcmp(y-a.y)==0;} I const bool operator != (const Vector &a) const {return dcmp(x-a.x)!=0||dcmp(y-a.y)!=0;} }; typedef Vector Point; I Vector Normal(Vector a){return Vector(-a.y,a.x);} // counterclockwise I db Dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;} I db Cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;} I db Len(Vector a){return sqrt(Dot(a,a));} I db Len2(Vector a){return Dot(a,a);} I db Angle(Vector a,Vector b){return acos(Dot(a,b)/Len(a)/Len(b));} I Vector Rotate(Vector a,db rad){return Vector(cos(rad)*a.x-sin(rad)*a.y,sin(rad)*a.x+cos(rad)*a.y);} struct Line { Point a,b; // a->b Line(){} Line(Point aa,Point bb){a=aa,b=bb;} }; I db DisL(Point p,Line l){Vector u=p-l.a,v=l.b-l.a;return fabs(Cross(u,v))/Len(v);} // dist to line I db DisS(Point p,Point a,Point b) // dist to segment { if (a==b) return Len(p-a); Vector v1=b-a,v2=p-a,v3=p-b; if (dcmp(Dot(v1,v2))<0) return Len(v2); if (dcmp(Dot(v1,v3))>0) return Len(v3); return fabs(Cross(v1,v2))/Len(v1); } I bool OnLeft(Point p,Line l){return dcmp(Cross(p-l.a,l.b-l.a))<=0;} I bool OnLine(Point p,Line l){return dcmp(Cross(p-l.a,l.a-l.b))==0;} I bool OnSeg(Point p,Point a,Point b){return dcmp(Cross(p-a,a-b))==0&&dcmp(Cross(p-a,p-b))<0&&p!=a&&p!=b;} I Point LI(Line l1,Line l2) // line intersection { Vector v=l1.a-l2.a,v1=l1.b-l1.a,v2=l2.b-l2.a; db t=Cross(v,v2)/Cross(v2,v1); return l1.a+v1*t; } I bool LSI(Line l,Point a,Point b) // line-seg intersection { Vector v=l.b-l.a,v1=a-l.a,v2=b-l.a; return dcmp(Cross(v,v1))!=dcmp(Cross(v,v2)); } I bool SSI(Point a1,Point b1,Point a2,Point b2) /*seg-seg intersection*/ {Line l1(a1,b1),l2(a2,b2);return LSI(l1,a2,b2)&&LSI(l2,a1,b1);} I Point Circumcenter(Point a,Point b,Point c) // wai xin { Point p=(a+b)/2,q=(a+c)/2; Vector u=Normal(b-a),v=Normal(c-a); if (!dcmp(Len(a-b)+Len(a-c)-Len(b-c))) return (b+c)/2; if (!dcmp(Len(a-b)+Len(b-c)-Len(a-c))) return (a+c)/2; if (!dcmp(Len(a-c)+Len(b-c)-Len(a-b))) return (a+b)/2; return LI(Line(p,p+u),Line(q,q+v)); } I Point Barycenter(Point a,Point b,Point c) /*zhong xin*/ {return (a+b+c)/3;} I bool PolarCmp(Point a,Point b){db c=Cross(a,b);return dcmp(c)==0?a.x<b.x:dcmp(c)>0;} db PolygonArea(Point *p,int n) { db ret=0; rep(i,2,n-1) ret+=Cross(p[i]-p[1],p[i+1]-p[1]); return fabs(ret/2); } int InPolygon(Point *poly,int n,Point p) // 1:in 0:out -1:on { int ret=0; rep(i,1,n) { int j=i%n+1; if (OnSeg(p,poly[i],poly[j])||p==poly[i]||p==poly[j]) return -1; if (poly[i].y==poly[j].y) continue; int tmp=(poly[i].y>poly[j].y?i:j); if (p.y==poly[tmp].y&&p.x<poly[tmp].x) { ret^=1; continue; } tmp=(poly[i].y<poly[j].y?i:j); if (p.y==poly[tmp].y&&p.x<poly[tmp].x) continue; if (SSI(p,p+Vector(1e18,0),poly[i],poly[j])) ret^=1; } return ret; } bool IsConvex(Point *poly,int n) { int now=0,last=0; rep(i,1,n) { int j=i+1,k=i+2;j>n?j-=n:0;k>n?k-=n:0; now=dcmp(Cross(poly[k]-poly[j],poly[j]-poly[i])); if (now*last<0) return 0; last=now; } return 1; } int GetConvex(Point *p,int n,Point *ret) // return the size of the convex { sort(p+1,p+n+1);n=unique(p+1,p+n+1)-p-1; int m=0; rep(i,1,n) { while (m>1&&dcmp(Cross(ret[m]-ret[m-1],p[i]-ret[m-1]))<=0) --m; ret[++m]=p[i]; } int _m=m; drep(i,n-1,1) { while (m>_m&&dcmp(Cross(ret[m]-ret[m-1],p[i]-ret[m-1]))<=0) --m; ret[++m]=p[i]; } if (n>1) --m; return m; } db RotatingCalipers(Point *p,int n) { db ret=0; if (n==1) return ret; if (n==2) return Len(p[1]-p[2]); int now=1;Point _=p[n+1];p[n+1]=p[1]; rep(i,1,n) { while (dcmp(DisL(p[now],Line(p[i],p[i+1]))-DisL(p[now+1],Line(p[i],p[i+1])))<0) now=now%n+1; ret=max(ret,max(Len(p[now]-p[i]),Len(p[now]-p[i+1]))); } p[n+1]=_; return ret; } db MinCircleCover(Point *p,int n,Point &O) // return the minimum radius { O=p[1];db r=0; rep(i,2,n) if (dcmp(r-Len(p[i]-O))<0) { O=p[i],r=0; rep(j,1,i-1) if (dcmp(r-Len(p[j]-O))<0) { O=(p[i]+p[j])/2,r=Len(O-p[j]); rep(k,1,j-1) if (dcmp(r-Len(p[k]-O))<0) { O=Circumcenter(p[i],p[j],p[k]); r=Len(O-p[k]); } } } return r; } int n; struct hh{db k,b;int id;}a[sz]; inline bool cmp(const hh &x,const hh &y){return x.k==y.k?x.b>y.b:x.k<y.k;} Line aa[sz]; int top,s[sz]; int main() { file(); db x,y; read(n); rep(i,1,n) read(x,y),a[i]=(hh){x,y,i}; sort(a+1,a+n+1,cmp); rep(i,1,n) aa[i].a=Point(0,a[i].b),aa[i].b=Point(1,a[i].k+a[i].b); s[top=1]=1; rep(i,2,n) if (a[i].k!=a[i-1].k) { while (top>1&&dcmp(LI(aa[s[top]],aa[s[top-1]]).x-LI(aa[s[top-1]],aa[i]).x)>=0) --top; s[++top]=i; } rep(i,1,top) s[i]=a[s[i]].id; sort(s+1,s+top+1); rep(i,1,top) printf("%d ",s[i]); }
- 1
信息
- ID
- 2267
- 时间
- 1500ms
- 内存
- 125MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者