hdu5033 單調棧

題意:給定很多摩天大樓的高度和一些觀測點 然後要求求出每一個觀測點仰望天空的最大角度

解法:維護一個斜率下降的序列 這樣就可以隱去一些凹點 這些凹點是不會影響後來的點的 

#include<set>
#include<map>
#include<cstdio>
#include<iostream>
#include<string.h>
#include<math.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define maxn 555555
#define mid ((l+r)>>1)
#define pi acos(-1.0)
int n,m,co;
double xx,hl,hr;
struct node{
    double xi,hi,ansl,ansr;
    int id;
}point[maxn],st[maxn];
bool cmp(node x,node y){return x.xi<y.xi;}
int cnt=0;
double ans[maxn],ans1[maxn];
int main(){
    int _;scanf("%d",&_);
    for(int z=1;z<=_;++z){
        printf("Case #%d:\n",z);
        scanf("%d",&n);
        for(int i=0;i<n;++i){
            scanf("%lf%lf",&point[i].xi,&point[i].hi);
            point[i].id=0;
        }
        cnt=n;
        scanf("%d",&m);
        for(int i=1;i<=m;++i){
            scanf("%lf",&point[cnt].xi);
            point[cnt].id=i;
            point[cnt].hi=0;
            cnt++;
        }
        
        for(int i=0;i<cnt;++i)point[i].ansl=-1,point[i].ansr=-1;
        sort(point,point+cnt,cmp);
//        for(int i=0;i<cnt;++i){
//            printf("%lf %lf\n",point[i].xi,point[i].hi);
//        }
        printf("\n");
        int top=0;
        for(int i=0;i<cnt;++i){
            while(top>=1&&point[i].hi>st[top].hi){
                top--;
            }
            while(top>=2){
                double xl=(st[top].hi-point[i].hi)/(point[i].xi-st[top].xi);
                if(xl<=st[top].ansl){
                    top--;
                }else{
                    break;
                }
            }
            st[++top]=point[i];
            if(top==1){
                st[top].ansl=0;
            }else{
            st[top].ansl=(st[top-1].hi-st[top].hi)/(st[top].xi-st[top-1].xi);
              ans[st[top].id]=st[top].ansl;
//                printf("i:%d ansl:%lf id:%d\n",i,st[top].ansl,st[top].id);
            }
        }top=0;
        for(int i=cnt-1;i>=0;--i){
            while(top>=1&&point[i].hi>st[top].hi){
                top--;
            }
            while(top>=2){
                double xl=(st[top].hi-point[i].hi)/(st[top].xi-point[i].xi);
                if(xl<=st[top].ansr){
                    top--;
                }else{
                    break;
                }
            }
            st[++top]=point[i];
            if(top==1){
                st[top].ansr=0;
            }else{
            st[top].ansr=(st[top-1].hi-st[top].hi)/(st[top-1].xi-st[top].xi);
                ans1[st[top].id]=st[top].ansr;
//                printf("i:%d ansr:%lf id:%d\n",i,st[top].ansr,st[top].id);
            }
        }
//        printf("%lf %lf\n",ans[1],ans1[1]);
        
        for(int i=1;i<=m;++i){
            printf("%.10f\n",
            (180.0)*(pi/2-atan(ans[i]))/pi+(180.0)*(pi/2-atan(ans1[i]))/pi);
        }
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章