hdu5033 Building 单调队列

来源:互联网 发布:域名备案有什么用 编辑:程序博客网 时间:2024/04/29 15:38
//    hdu5033 Building 单调队列////    题目大意:////    n栋大楼,有一个高度h和位置x,现在有一个人高度为0,有q个询问//    每个询问有一个位置x,求在位置x能看到天空的最大的角度。////    解题思路:////    首先得想到将q个询问的位置作为一栋大楼放在整个大楼中考虑,这样//    问题就比较一致,也比较容易处理啦。////    想象一下,每次从左往右走,对于当前位置的左半边的90度内,看天的角度是//    逐渐减小的,这样,如果当前位置的左边比当前位置要低,那么当前位置就挡住了//    之前的更矮的,也就是说之后的位置是不可能看到比当前更矮的大楼了,这样,就可//    以看成是一个单调的序列,序列中元素高度单调递减,即所谓的单调队列。但仅仅只是//    这样是不够的,也会存在比当前元素(设为h)高设为h1,在队列中h1前面的元素是h2,虽然//    h1是比h大,但是如果顺着h1的高度看过去,会被h2挡住,这时h1是没有作用的,也要将//    这个元素从队列中移除。////    当遇到的大楼要查询的位置的时候,此时队列最后的一个元素并不一定是最优的值,因为//    这样的值可能是不合法的,比如上面的h1会被h2挡住,并不会看到天空。照样移除这样的元素//    最后,队列的最后一个元素就是解。////    右边的问题完全可以转化为左边的问题,只是从右往左处理而已。//////    感悟:////    这道题是14年北京区的网赛的一道题目,当时的我虽然看懂了题目的意思,但是真的完全不会做。//    直到现在伟大的MW大咖,说是单调队列可以做,我就做了,但是卡了一天半,还是想不出来具体怎么解//    首先将询问的位置当作大楼这一点我想到了,维持高度递减的单调队列我想到了,就是最后一种情况没有//    想到,更不知道要怎么处理,在伟大的MW大咖的敦敦教诲还有耐心的提示下,终于终于想到了解决的办法//    不容易啊不容易。在此真诚感谢MW大咖~////    过程无疑会有很多的疑惑,一个地方不慎,满盘皆输,找到一处的错误,心里十分的欣喜,特别是在ac//    之后,那种心情,实在是难以描述,感觉到自己的付出,真的是有回报,以前不懂的东西,自己认真学//    总会有收获,哪怕收获是那么一点点,微不足道,但收获就是收获,没有这个能让人更加欣喜啦,痛苦并快乐着//    十分的享受,还是那句话,继续练吧~~~#include <cstdio>#include <algorithm>#include <cmath>#include <iostream>#include <cstring>using namespace std;const int MAX_N = 2e5 + 9;const double PI = acos(-1.0);int n,q;double deqh[MAX_N];double deqx[MAX_N];double angle[MAX_N];struct node {    double pos;    double h;    int id;    node(){    }    node(double pos,double h,int id):pos(pos),h(h),id(id){    }};node sky[MAX_N];bool cmp(node a,node b){    return a.pos < b.pos;}void input(){    scanf("%d",&n);    double x,h;    for (int i = 1;i <= n;i++){        scanf("%lf%lf",&x,&h);        sky[i] = node(x,h,0);    }    scanf("%d",&q);    for (int i = 1;i <= q;i++){        scanf("%lf",&x);        sky[i+n] = node(x,0.0,i);        angle[i] = 0.0;    }    n += q;    sort(sky+1,sky+n+1,cmp);}double getk(double a,double b){    return fabs(a/b);}void getleft(){    int head,tail;    head = tail = 0;    for (int i=1;i<=n;i++){        if (sky[i].id){            while(head + 1 < tail){                double k1 = getk(deqh[tail-1],deqx[tail-1]-sky[i].pos);                double k2 = getk(deqh[tail-2],deqx[tail-2]-sky[i].pos);                if (k1 <= k2)                    tail--;                else break;            }            angle[sky[i].id] += atan(deqh[tail-1]/fabs(deqx[tail-1]-sky[i].pos));        }else {            while(head < tail && deqh[tail-1] < sky[i].h)                tail--;            while(head + 1 < tail){                double k1 = getk(deqh[tail-1]-sky[i].h,deqx[tail-1]-sky[i].pos);                double k2 = getk(deqh[tail-2]-sky[i].h,deqx[tail-2]-sky[i].pos);                if (k1 <= k2)                    tail--;                else                    break;            }            deqh[tail] = sky[i].h;            deqx[tail++] = sky[i].pos;        }    }}void getright(){    int head,tail;    head = tail = 0;    for (int i = n;i >= 1;i--){        if (sky[i].id){            while(head + 1 < tail){                double k1 = getk(deqh[tail-1],deqx[tail-1]-sky[i].pos);                double k2 = getk(deqh[tail-2],deqx[tail-2]-sky[i].pos);                if (k1 <= k2)                    tail--;                else                    break;            }            angle[sky[i].id] += atan(deqh[tail-1]/fabs(deqx[tail-1]-sky[i].pos));        }else {            while(head < tail && deqh[tail-1] < sky[i].h)                tail--;            while(head + 1 < tail){                double k1 = getk(deqh[tail-1]-sky[i].h,deqx[tail-1] - sky[i].pos);                double k2 = getk(deqh[tail-2]-sky[i].h,deqx[tail-2] - sky[i].pos);                if (k1 <= k2){                    tail--;                }else                    break;            }            deqh[tail] = sky[i].h;            deqx[tail++] = sky[i].pos;        }    }}void solve(){    getleft();    getright();    for (int i=1;i<=q;i++){        printf("%.10lf\n",(PI - angle[i]) * 180.0 / PI);    }}int main(){    int t;    //freopen("1.txt","r",stdin);    scanf("%d",&t);    int kase = 1;    while(t--){        input();        printf("Case #%d:\n",kase++);        solve();    }}

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 淘宝支付不了了怎么办 手机图标变黑了怎么办 商品没有支付宝怎么办 金立s8热点打不开怎么办 淘宝店铺异常2怎么办 付款付错了怎么办 手机淘宝太卡怎么办 卖家不同意退货怎么办 游戏退出无响应怎么办 手机淘宝购物车打不开怎么办 淘宝店铺没有访客怎么办 淘宝店铺0流量怎么办 微信经常封号怎么办 网上拍卖堂违约怎么办 dnf4开组队制裁怎么办 红酒木塞丢了怎么办 红酒塞子进去了怎么办 淘金币即将过期怎么办 淘金币过期怎么办2018 换详情排名下降怎么办 长城宽带不用了怎么办 快递到了想退货怎么办 淘宝退货商家拒收怎么办 淘宝运费险失败怎么办 忘记购买运费险怎么办 咸鱼买家申请退款怎么办 熟猪肉有点变味怎么办 和领导意见不一致怎么办 骑手提前点送达怎么办 ubuntu安装报错怎么办 液相色谱两峰分不开怎么办 液相色谱柱老堵怎么办? 没有装usb驱动怎么办 ipad速度越来越慢怎么办 美萍管理软件打不开怎么办 小米4开机黑屏怎么办 小米电脑死机了怎么办 小米8手机死机怎么办 oppa7开不了机怎么办 oppo手机wlan打不开怎么办 三星s6进水黑屏怎么办