zoukankan      html  css  js  c++  java
  • hdu 5033 模拟+单调优化

    http://acm.hdu.edu.cn/showproblem.php?pid=5033

    平面上有n个建筑,每个建筑由(xi,hi)表示,m组询问在某一个点能看到天空的视角范围大小。

    维护一个凸包,据说可以用单调栈

    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <cstring>
    #include <string>
    #include <set>
    #include <map>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define RD(x) scanf("%d",&x)
    #define RD2(x,y) scanf("%d%d",&x,&y)
    #define clr0(x) memset(x,0,sizeof(x))
    typedef long long LL;
    const double pi = acos(-1.0);
    const int INF = 2000000007;
    map <double,int> hash;
    struct node{
        double x,h;
    }s[100005];
    int n,ll[100005],rr[100005];
    double ans;
    set <double> st;
    bool cmp(node a,node b)
    {
        return a.x < b.x;
    }
    int main(){
        int _,q,cas = 1;
        RD(_);
        while(_--){
            printf("Case #%d:
    ",cas++);
            RD(n);
            st.clear();
            hash.clear();
            for(int i = 1;i <= n;++i){
                scanf("%lf%lf",&s[i].x,&s[i].h);
                ll[i] = rr[i] = i;
                st.insert(s[i].x);
            }
            sort(s+1,s+n+1,cmp);
            for(int i = 1;i <= n;++i){
                hash[s[i].x] = i;
                for(int j = i - 1;j >= 1;--j){
                    if(s[j].h > s[i].h){
                        ll[i] = j;
                        break;
                    }
                    if(j == ll[j])  break;
                }
            }
            for(int i = n;i >= 1;--i){
                for(int j = i + 1;j <= n;++j){
                    if(s[j].h > s[i].h){
                        rr[i] = j;
                        break;
                    }
                    if(j == rr[j])  break;
                }
            }
            RD(q);
            while(q--){
                double x;
                scanf("%lf",&x);
                int r = hash[*st.lower_bound(x)],l = r - 1;
                double bst = s[r].h/fabs(s[r].x - x);
                while(r != rr[r]){
                    r = rr[r];
                    if(s[r].h > bst*(s[r].x-x))
                        bst = s[r].h/(s[r].x-x);
                }
                ans = pi - atan(bst);
                bst = s[l].h/fabs(x - s[l].x);
                while(l != ll[l]){
                    l = ll[l];
                    if(s[l].h > bst*(x-s[l].x))
                        bst = s[l].h/(x-s[l].x);
                }
                ans -= atan(bst);
                printf("%.9lf
    ",180.0*ans/pi);
            }
         }
         return 0;
     }


  • 相关阅读:
    LeetCode 297. 二叉树的序列化与反序列化
    LeetCode 14. 最长公共前缀
    LeetCode 1300. 转变数组后最接近目标值的数组和
    bigo一面凉经
    LeetCode 128.最长连续序列
    LeetCode中二分查找算法的变种
    LeetCode 93. 复原IP地址
    LeetCode 1004. 最大连续1的个数 III
    LeetCode 1282. 用户分组
    多线程理解
  • 原文地址:https://www.cnblogs.com/zibaohun/p/4046817.html
Copyright © 2011-2022 走看看