1. 程式人生 > >bzoj1007/luogu3194 水平可見直線 (單調棧)

bzoj1007/luogu3194 水平可見直線 (單調棧)

tin class ++ col main bsp define 一個 inline

先按斜率從小到大排序,然後如果排在後面的點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 }

bzoj1007/luogu3194 水平可見直線 (單調棧)