bzoj1007:[HNOI2008]水平可见直线
思路:首先按斜率排序,如果斜率相同就取截距最大的,显然截距小的会被覆盖而对答案没有贡献,然后考虑斜率不同的如何统计答案,可以用一个单调栈维护,当前新插入的直线显然斜率是要比当前栈顶斜率要大的,然后如果新插入的直线l[i]与stack[top]的交点在stack[top]与stack[top-1]的交点的右边,那么就不需要退栈直接加进来就好了,否则就要退栈直到条件成立。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; #define maxn 50005 #define eps 1e-7 int n,cnt,top,stack[maxn]; struct line{ double k,b; int id; bool operator <(const line &a)const{return k<a.k ||(fabs(k-a.k)<eps && b<a.b);} }l[maxn]; bool cmp(int a,int b){return l[a].id<l[b].id;} double getpoint_x(line a,line b){ return (b.b-a.b)/(a.k-b.k); } bool check(line a,line b,line c){ return getpoint_x(a,b)>=getpoint_x(b,c); } int main(){ scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%lf%lf",&l[i].k,&l[i].b),l[i].id=i; sort(l+1,l+n+1); for (int i=1;i<=n;i++){ while (fabs(l[i].k-l[i+1].k)<eps) i++; while (top>=2 && check(l[stack[top-1]],l[stack[top]],l[i])) top--; stack[++top]=i; } sort(stack+1,stack+top+1,cmp); for (int i=1;i<=top;i++) printf("%d ",l[stack[i]].id); return 0; }