数据结构 单调栈+几何 摩天大楼【HDU 5033 】

HDU 5033

题目大意:

就是一个人来到充满摩天大楼的城市,所有大楼没有宽度。建一直角坐标系,给出每个建筑的高度,现在求人站在(x,0)处能够看到天空的范围。(即不被摩天大楼阻挡)。答案只需要给出视角大小。
还是想了一会才想出。.对于一个人能看到的左界,我们可以得到下式:

kmaxxi=min((HjHi)/(XjXi)),j<=i k m a x x i = m i n ( ( H j − H i ) / ( X j − X i ) ) , j <= i

用求出左界的斜率即可反解该范围的视角的角。而求最小即用单调栈维护斜率单减即可。右界同理可得。
有SPJ虚什么精度差?

#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn=1000100,inf=1e9;
const double pi=3.1415926535;
int  t,n,cnt;
stack int,double> > s;//第一个是当前元素编号,第二个是与上一个元素的斜率。 
struct node{
    int x,h,bian;
    double l,r;
}a[maxn];
bool cmp(node p,node q){
    return p.xbool cmp2(node p,node q){
    return p.biandouble getk(int x,int y){
    double x1=a[x].x,x2=a[y].x,y1=a[x].h,y2=a[y].h;
    return (y2-y1)/(x2-x1);
}
int main(){
    int i,j,q;double k,a1,a2;
    scanf("%d",&t);
    for(j=1;j<=t;j++){
        scanf("%d",&n);
        printf("Case #%d\n",j);
        cnt=0;
        for(i=1;i<=n;i++){
            scanf("%d%d",&a[i].x,&a[i].h);
            a[i].bian=inf;//大楼的编号为正无穷 
        }
        cnt=n;
        scanf("%d",&q);
        for(i=1;i<=q;i++){
            cnt++;
            scanf("%d",&a[cnt].x);
            a[cnt].bian=i;
            a[cnt].h=0;
        }
        sort(a+1,a+cnt+1,cmp);//把人和摩天大楼同时排序,不用分类讨论。 
        while(!s.empty())s.pop();
        for(i=1;i<=cnt;i++){//求左界,维护斜率单减 
            while(!s.empty()){
                k=getk(s.top().first,i);
                if(k>=s.top().second)s.pop();
                else break;
            }
            if(s.empty()){
                a[i].l=0;
                s.push(make_pair(i,double(inf)));
            }
            else {
                a[i].l=getk(s.top().first,i);
                s.push(make_pair(i,a[i].l));
            }
        }
        while(!s.empty())s.pop();
        for(i=cnt;i>=1;i--){//求右界,维护斜率单增 
            while(!s.empty()){
                k=getk(s.top().first,i);
                if(k<=s.top().second)s.pop();
                else break;
            }
            if(s.empty()){
                a[i].r=0;
                s.push(make_pair(i,double(-inf)));
            }
            else {
                a[i].r=getk(s.top().first,i);
                s.push(make_pair(i,a[i].r));
            }
        }
        sort(a+1,a+cnt+1,cmp2);
        for(i=1;i<=q;i++){
            a1=atan(abs(a[i].l));
            a2=atan(abs(a[i].r));
            printf("%.10lf\n",(pi-a1-a2)/pi*180);
        }
    }
    return 0;
}

你可能感兴趣的:(数据结构)