bzoj1007/luogu3194 水平可见直线 (单调栈)
先按斜率从小到大排序,然后如果排在后面的点B和前面的点A的交点是P,那B会把A在P的右半段覆盖掉,A会把B在P的左半段覆盖掉。
然后如果我们现在又进来了一条线,它跟上一条的交点还在上一条和上上条的左边,这就说明上一条完全被覆盖了
这样的话,维护一个单调栈做一做就可以了
(要先处理一下,斜率相同的只留下B最大的,而且会有重合的线,都要输出)
1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define ll long long 4 using namespace std; 5 const int maxn=50050; 6 7 ll rd(){ 8 ll x=0;char c=getchar();int neg=1; 9 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 10 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 11 return x*neg; 12 } 13 14 struct Line{ 15 int a,b,i; 16 }p[maxn],q[maxn]; 17 int N,NN,stk[maxn],sh; 18 bool flag[maxn]; 19 20 inline bool cmp(Line a,Line b){ 21 return a.a==b.a?a.b>b.b:a.a<b.a; 22 } 23 24 inline double getx(Line a,Line b){ 25 return (double)(b.b-a.b)/(a.a-b.a); 26 } 27 inline bool nsame(int a,int b){ 28 return q[a].a!=q[b].a||q[a].b!=q[b].b; 29 } 30 31 int main(){ 32 int i,j,k; 33 N=rd();for(i=1;i<=N;i++){ 34 p[i].a=rd(),p[i].b=rd();p[i].i=i; 35 } 36 sort(p+1,p+N+1,cmp); 37 for(i=1,j=0;i<=N;i++){ 38 if(p[i].a==p[i-1].a&&p[i].b<p[i-1].b) continue; 39 q[++j]=p[i]; 40 }NN=j; 41 stk[sh=1]=1; 42 for(i=2;i<=NN;i++){ 43 while(sh>=2&&nsame(stk[sh],i)&&(getx(q[i],q[stk[sh]])<=getx(q[stk[sh]],q[stk[sh-1]]))) sh--; 44 stk[++sh]=i; 45 }for(i=sh;i;i--) flag[q[stk[i]].i]=1; 46 for(i=1;i<=N;i++) if(flag[i]) printf("%d ",i); 47 return 0; 48 }