數據結構 單調棧+幾何 摩天大樓【HDU 5033 】

HDU 5033

題目大意:

就是一個人來到充滿摩天大樓的城市,所有大樓沒有寬度。建一直角座標系,給出每個建築的高度,現在求人站在(x,0)處能夠看到天空的範圍。(即不被摩天大樓阻擋)。答案只需要給出視角大小。
還是想了一會纔想出。.對於一個人能看到的左界,我們可以得到下式:

kmaxxi=min((HjHi)/(XjXi)),j<=i

用求出左界的斜率即可反解該範圍的視角的角。而求最小即用單調棧維護斜率單減即可。右界同理可得。
有SPJ虛什麼精度差?
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=1000100,inf=1e9;
const double pi=3.1415926535;
int  t,n,cnt;
stack <pair<int,double> > s;//第一個是當前元素編號,第二個是與上一個元素的斜率。 
struct node{
    int x,h,bian;
    double l,r;
}a[maxn];
bool cmp(node p,node q){
    return p.x<q.x;
}
bool cmp2(node p,node q){
    return p.bian<q.bian;
}
double 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章