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
- hdu5033 Building 单调队列
- hdu5033 Building单调栈
- HDU5033-Building(维护单调栈)
- hdu5033 Building(单调栈)
- HDU5033 building
- hdu5033 Building 北京网络赛B题 单调栈
- hdu5033 Building 凸包
- hdu5033 单调栈
- HDU 5033 Building 单调队列
- HDU5033 - Building(暴力,DP思想)
- HDU5033
- Hdu5033
- 单调栈 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- java.lang.OutOfMemoryError: Java heap space解决方案
- 在32位ubuntu中安装docker并且成功启动容器
- 新的开始
- UIView及其子类
- Hibernate入门
- hdu5033 Building 单调队列
- ISE中下载Xilinx的bit文件失败时的处理方案
- 平平淡淡才是真 安安乐乐才是福
- 客户端开发--2控制器开发准备(1)【界面布局和行为控制】
- 移动广告名词
- 面向对象的三大基本特征
- 【进阶android】Volley源码分析——Volley的线程
- CString中Format函数与格式输入与输出
- UVA 10420(排序检索)