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 }

 

posted @ 2018-09-12 12:50  Ressed  阅读(146)  评论(0编辑  收藏  举报