BZOJ1007 HNOI2008 水平可见直线 计算几何
题意:给定N条直线,求由这N条直线组成的,满足上方没有直线交点的边界由哪些直线组成
题解:我这STL用的真是闷声做大死,多亏不卡常……显然所求的边界中的直线k肯定单调的,所以首先将直线按k升序(第一关键字),b降序(第二关键字)进行排序。然后枚举每一条直线,用单调栈s维护这个直线集,若堆顶元素s[0]能被次栈顶直线s[1]和当前直线覆盖l[i],则满足s[0]与l[i]的交点在s[1]与s[0]交点的左侧,按照这一规则不断弹栈,然后加入l[i]。
#include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> #include <vector> using namespace std; const int MAXN=50000+2; struct Line{ int t; double k,b; Line(){} Line(double _k,double _b):k(_k),b(_b){} }l[MAXN]; struct Point{ double x,y; }; int N; vector<Line> s; bool cmp1(Line x,Line y){ return x.k==y.k?x.b>y.b:x.k<y.k;} bool cmp2(Line x,Line y){ return x.t<y.t;} Point Calc(Line x,Line y){ Point ans; ans.x=(y.b-x.b)/(x.k-y.k),ans.y=ans.x*x.k+x.b; return ans; } int main(){ cin >> N; for(int i=1;i<=N;i++) cin >> l[i].k >> l[i].b,l[i].t=i; sort(l+1,l+N+1,cmp1),s.push_back(l[1]); for(int i=2;i<=N;i++){ while(s.size()>1 && Calc(l[i],s[0]).x<=Calc(s[0],s[1]).x) s.erase(s.begin()); s.insert(s.begin(),l[i]); } N=s.size(),sort(s.begin(),s.end(),cmp2); for(int i=0;i<N;i++) cout << s[i].t << " "; return 0; }