HDU 5033 Building(单调栈)
HDU 5033 Building(单调栈)
题目链接http://acm.hdu.edu.cn/showproblem.php?pid=5033
Description
Once upon a time Matt went to a small town. The town was so small and narrow that he can regard the town as a pivot. There were some skyscrapers in the town, each located at position xi with its height hi. All skyscrapers located in different place. The skyscrapers had no width, to make it simple. As the skyscrapers were so high, Matt could hardly see the sky.Given the position Matt was at, he wanted to know how large the angle range was where he could see the sky. Assume that Matt's height is 0. It's guaranteed that for each query, there is at least one building on both Matt's left and right, and no building locate at his position.
Input
The first line of the input contains an integer T, denoting the number of testcases. Then T test cases follow.
Each test case begins with a number N(1<=N<=10^5), the number of buildings.
In the following N lines, each line contains two numbers, xi(1<=xi<=10^7) and hi(1<=hi<=10^7).
After that, there's a number Q(1<=Q<=10^5) for the number of queries.
In the following Q lines, each line contains one number qi, which is the position Matt was at.
Output
For each test case, first output one line "Case #x:", where x is the case number (starting from 1).
Then for each query, you should output the angle range Matt could see the sky in degrees. The relative error of the answer should be no more than 10^(-4).
Sample Input
3
3
1 2
2 1
5 1
1
4
3
1 3
2 2
5 1
1
4
3
1 4
2 3
5 1
1
4
Sample Output
Case #1:
101.3099324740
Case #2:
90.0000000000
Case #3:
78.6900675260
题意:
在一条坐标轴上给你n个楼的高度,再问你再某个坐标你所能看到天空的最大视角。
题解:
首先这个数据范围明显不能105*105暴力跑。在看了题解之后,了解到可以用一个叫做单调栈的东西。当规定了栈顶到栈低的顺序,那么在每次压栈的时候则考虑是否满足这个顺序,满足入栈,不满足栈顶弹出然后直到满足压栈。
首先是最大角度,这里首先使用了一个非常巧妙的方式。
首先我们可以将这个夹角看成以该点作垂线和左右两条之间的夹角之和。这样如果我们可以将该点的垂线和左边直线之间的夹角,再将坐标轴翻转,那么右边同样变成了上一个求出的方法,累加就好。
下面就是求垂线和左边的夹角。
这里某份题解同样用了一个非常巧妙的方式,因为查询点是高度为0,那么我们先把该点的纵坐标记作查询的顺序的负数(再按照横坐标顺序从小到大排序)。这样再后面的时候可以容易的判断是否为观察点,和容易记录半边角。
下面我们遍历所有的点,首先对于该点是查询点,那么我们开始判断栈顶的点能不能遮挡次栈顶的点,如果不能那么在后面的判断中也是不能遮挡的,则该点出栈,没有价值。直到找到这个点那么通过观察点的负值取负记录角度到输出结果。
对于非观察点,我们首先是判断该点是否比栈顶元素高,高的话明显可以遮挡出栈,不比栈顶元素高的的话我们再通过判断能否遮挡来确定栈顶元素是否出栈,然后将该点入栈。
判断函数,首先我们确定三个点a,b,c。c点是观察点,a的高度>b的高度,在我们建这个单调栈的时候我们就已经保证了这个。那么判断a->c的角度和b->c的角度,即可判断是否遮挡了。
代码:
#include <bits/stdc++.h>
using namespace std;
const double PI = acos(-1.0) ;
const int maxn = 100000+100;
struct Point {
int x,h;
bool operator < (const Point &R) const {
return x < R.x ;
}
};
Point s[maxn*2];
Point stk[maxn*2];
double ans[maxn] ;
int judge(Point a,Point b,Point c)
{
if (c.h <= 0) c.h = 0;
return (long long)(a.h-c.h)*(b.x-c.x) <= (long long)(b.h-c.h)*(a.x-c.x) ;
}
double angle(Point a,Point b)
{
return atan(1.0*(b.x-a.x)/a.h) ;
}
int n,q;
void solve()
{
int top = 0;
for (int i = 0; i < n+q; i++){
if (s[i].h <= 0){
while (top >= 2 && judge(stk[top-2],stk[top-1],s[i]))
top-- ;
ans[-s[i].h] += angle(stk[top-1],s[i]) ;
}else {
while (top && stk[top-1].h <= s[i].h)
top-- ;
while (top >= 2 && judge(stk[top-2],stk[top-1],s[i]))
top--;
stk[top++] = s[i] ;
}
}
}
int main()
{
int t;
scanf("%d",&t);
for (int _t = 1;_t <= t;_t++){
scanf("%d",&n);
for (int i = 0; i < n; i++)
scanf("%d %d",&s[i].x,&s[i].h) ;
scanf("%d",&q) ;
for (int i = 0; i < q; i++){
scanf("%d",&s[i+n].x);
s[i+n].h = -i;
}
memset(ans,0,sizeof ans) ;
sort(s,s+n+q) ;
solve();
reverse(s,s+n+q) ;
for (int i = 0; i < n+q; i++)
s[i].x = 10000000-s[i].x ;
solve() ;
printf("Case #%d:\n",_t) ;
for (int i = 0 ; i <q; i++)
printf("%.10lf\n",ans[i]*180/PI) ;
}
return 0;
}
HDU 5033 Building(单调栈)的更多相关文章
- hdu 5033 Building (单调栈 或 暴力枚举 )
Description Once upon a time Matt went to a small town. The town was so small and narrow that he can ...
- HDU - 5033 Building (单调栈+倍增)
题意:有一排建筑,每座建筑有一定的高度,宽度可以忽略,求在某点的平地上能看到天空的最大角度. 网上的做法基本都是离线的...其实这道题是可以在线做的. 对于向右能看到的最大角度,从右往左倍增维护每个时 ...
- HDU 5033 Building(单调栈维护凸包)
盗张图:来自http://blog.csdn.net/xuechelingxiao/article/details/39494433 题目大意:有一排建筑物坐落在一条直线上,每个建筑物都有一定的高度, ...
- hdu - 5033 - Building(单调栈)
题意:N 幢楼排成一列(1<=N<=10^5),各楼有横坐标 xi(1<=xi<=10^7) 以及高度 hi(1<=hi<=10^7),在各楼之间的Q个位置(1&l ...
- HDU 5033 Building(北京网络赛B题) 单调栈 找规律
做了三天,,,终于a了... 11724203 2014-09-25 09:37:44 Accepted 5033 781MS 7400K 4751 B G++ czy Building Time L ...
- HDU 5033 Building (维护单调栈)
题目链接 题意:n个建筑物,Q条询问,问所在的位置,看到天空的角度是多少,每条询问的位置左右必定是有建筑物的. 思路 : 维护一个单调栈,将所有的建筑物和所有的人都放到一起开始算就行,每加入一个人,就 ...
- hdu 5033 模拟+单调优化
http://acm.hdu.edu.cn/showproblem.php?pid=5033 平面上有n个建筑,每个建筑由(xi,hi)表示,m组询问在某一个点能看到天空的视角范围大小. 维护一个凸包 ...
- Largest Rectangle in a Histogram HDU - 1506 (单调栈)
A histogram is a polygon composed of a sequence of rectangles aligned at a common base line. The rec ...
- HDU5033 building 单调栈+计算几何
正解:单调栈 解题报告: 哇生气辽QAQ本来打了半天feel good都快调出来了然后说换题了QAQ(所以可能那题的代码会过一阵子再放上来了QAQ 不过还是大爆手速打了一通拿到首杀了嘻嘻 美滋滋辽 然 ...
随机推荐
- 博客已迁移到lizhug.com
新的博客地址 http://lizhug.com
- “MVC+Nhibernate+Jquery-EasyUI” 信息发布系统 第四篇(用户管理功能的实现)
“MVC+Nhibernate+Jquery-EasyUI” 信息发布系统 第四篇(用户管理功能的实现) 一.前三篇的内容是否对您有帮助呢?如果有的话,请您继续关注这篇吧,这篇主要是实现”用户管理“的 ...
- CSS 实现的各种球体效果
CSS 实现的各种球体效果[附在线演示] CSS 可以实现很多你想不到的效果,今天我们来尝试使用 CSS 实现各种球体效果.有两种方法可以实现,第一种是使用大量的元素创建实际的 3D 球体,这种方法有 ...
- 公共建筑能耗监测平台的GPRS通讯服务器的开发方法分享
公共建筑能耗监测平台的GPRS通讯服务器的开发方法分享 在这个文章里面我将用一个实际的案例来分享如何来构建一个能够接受3000+个连接的GPRS通讯服务器软件,这个软件被我认为是一个艺术品,实现周期为 ...
- MBR . Have it removed!
To know what it is, https://wiki.archlinux.org/index.php/Master_Boot_Record For a SD card, dd if=/de ...
- SQL注入浅水攻防
啥是SQL注入(SQL Injection) 所谓SQL注入就是把SQL命令插入到表单的输入域或页面请求的查询字符串,欺骗服务器执行恶意的SQL命令.在某些表单中,用户输入的内容直接用来构造 (或影响 ...
- 趋势:Chrome为打包应用提供强大新特性
Chrome 7月9日刚为Chrome打包的应用提供了强大的访问Google服务例如Google统计.GoogleAPI和Google 钱包的能力,除此之外,还能够使用系统层面的服务包括蓝牙和原生应用 ...
- 动态修改ViewPagerIndicator CustomTabPageIndicator Tab标签文字颜色
ViewPagerIndicator 的CustomTabPageIndicator 默认是没有Tab选中修改TextView颜色特效的. 可以通过以下方式实现: 新建viewpager_title_ ...
- Android 消息传递之Bundle的使用——实现object对象传输(二)
上面学习了线程通过Massage发送字符串消息,Handler接收字符串消息,这样的形式来更新ui,接下来,一起分享怎么把一个对象利用消息机制发送出去,让主线程接收来更新ui. 下面就利用一个服务Se ...
- STURTS2 HELLOWORLD
4. <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC " ...
题目链接http://acm.hdu.edu.cn/showproblem.php?pid=5033
Description
Once upon a time Matt went to a small town. The town was so small and narrow that he can regard the town as a pivot. There were some skyscrapers in the town, each located at position xi with its height hi. All skyscrapers located in different place. The skyscrapers had no width, to make it simple. As the skyscrapers were so high, Matt could hardly see the sky.Given the position Matt was at, he wanted to know how large the angle range was where he could see the sky. Assume that Matt's height is 0. It's guaranteed that for each query, there is at least one building on both Matt's left and right, and no building locate at his position.
Input
The first line of the input contains an integer T, denoting the number of testcases. Then T test cases follow.
Each test case begins with a number N(1<=N<=10^5), the number of buildings.
In the following N lines, each line contains two numbers, xi(1<=xi<=10^7) and hi(1<=hi<=10^7).
After that, there's a number Q(1<=Q<=10^5) for the number of queries.
In the following Q lines, each line contains one number qi, which is the position Matt was at.
Output
For each test case, first output one line "Case #x:", where x is the case number (starting from 1).
Then for each query, you should output the angle range Matt could see the sky in degrees. The relative error of the answer should be no more than 10^(-4).
Sample Input
3
3
1 2
2 1
5 1
1
4
3
1 3
2 2
5 1
1
4
3
1 4
2 3
5 1
1
4
Sample Output
Case #1:
101.3099324740
Case #2:
90.0000000000
Case #3:
78.6900675260
题意:
在一条坐标轴上给你n个楼的高度,再问你再某个坐标你所能看到天空的最大视角。
题解:
首先这个数据范围明显不能105*105暴力跑。在看了题解之后,了解到可以用一个叫做单调栈的东西。当规定了栈顶到栈低的顺序,那么在每次压栈的时候则考虑是否满足这个顺序,满足入栈,不满足栈顶弹出然后直到满足压栈。
首先是最大角度,这里首先使用了一个非常巧妙的方式。首先我们可以将这个夹角看成以该点作垂线和左右两条之间的夹角之和。这样如果我们可以将该点的垂线和左边直线之间的夹角,再将坐标轴翻转,那么右边同样变成了上一个求出的方法,累加就好。
下面就是求垂线和左边的夹角。
这里某份题解同样用了一个非常巧妙的方式,因为查询点是高度为0,那么我们先把该点的纵坐标记作查询的顺序的负数(再按照横坐标顺序从小到大排序)。这样再后面的时候可以容易的判断是否为观察点,和容易记录半边角。
下面我们遍历所有的点,首先对于该点是查询点,那么我们开始判断栈顶的点能不能遮挡次栈顶的点,如果不能那么在后面的判断中也是不能遮挡的,则该点出栈,没有价值。直到找到这个点那么通过观察点的负值取负记录角度到输出结果。
对于非观察点,我们首先是判断该点是否比栈顶元素高,高的话明显可以遮挡出栈,不比栈顶元素高的的话我们再通过判断能否遮挡来确定栈顶元素是否出栈,然后将该点入栈。判断函数,首先我们确定三个点a,b,c。c点是观察点,a的高度>b的高度,在我们建这个单调栈的时候我们就已经保证了这个。那么判断a->c的角度和b->c的角度,即可判断是否遮挡了。
代码:
#include <bits/stdc++.h>
using namespace std;
const double PI = acos(-1.0) ;
const int maxn = 100000+100;
struct Point {
int x,h;
bool operator < (const Point &R) const {
return x < R.x ;
}
};
Point s[maxn*2];
Point stk[maxn*2];
double ans[maxn] ;
int judge(Point a,Point b,Point c)
{
if (c.h <= 0) c.h = 0;
return (long long)(a.h-c.h)*(b.x-c.x) <= (long long)(b.h-c.h)*(a.x-c.x) ;
}
double angle(Point a,Point b)
{
return atan(1.0*(b.x-a.x)/a.h) ;
}
int n,q;
void solve()
{
int top = 0;
for (int i = 0; i < n+q; i++){
if (s[i].h <= 0){
while (top >= 2 && judge(stk[top-2],stk[top-1],s[i]))
top-- ;
ans[-s[i].h] += angle(stk[top-1],s[i]) ;
}else {
while (top && stk[top-1].h <= s[i].h)
top-- ;
while (top >= 2 && judge(stk[top-2],stk[top-1],s[i]))
top--;
stk[top++] = s[i] ;
}
}
}
int main()
{
int t;
scanf("%d",&t);
for (int _t = 1;_t <= t;_t++){
scanf("%d",&n);
for (int i = 0; i < n; i++)
scanf("%d %d",&s[i].x,&s[i].h) ;
scanf("%d",&q) ;
for (int i = 0; i < q; i++){
scanf("%d",&s[i+n].x);
s[i+n].h = -i;
}
memset(ans,0,sizeof ans) ;
sort(s,s+n+q) ;
solve();
reverse(s,s+n+q) ;
for (int i = 0; i < n+q; i++)
s[i].x = 10000000-s[i].x ;
solve() ;
printf("Case #%d:\n",_t) ;
for (int i = 0 ; i <q; i++)
printf("%.10lf\n",ans[i]*180/PI) ;
}
return 0;
}
Description Once upon a time Matt went to a small town. The town was so small and narrow that he can ...
题意:有一排建筑,每座建筑有一定的高度,宽度可以忽略,求在某点的平地上能看到天空的最大角度. 网上的做法基本都是离线的...其实这道题是可以在线做的. 对于向右能看到的最大角度,从右往左倍增维护每个时 ...
盗张图:来自http://blog.csdn.net/xuechelingxiao/article/details/39494433 题目大意:有一排建筑物坐落在一条直线上,每个建筑物都有一定的高度, ...
题意:N 幢楼排成一列(1<=N<=10^5),各楼有横坐标 xi(1<=xi<=10^7) 以及高度 hi(1<=hi<=10^7),在各楼之间的Q个位置(1&l ...
做了三天,,,终于a了... 11724203 2014-09-25 09:37:44 Accepted 5033 781MS 7400K 4751 B G++ czy Building Time L ...
题目链接 题意:n个建筑物,Q条询问,问所在的位置,看到天空的角度是多少,每条询问的位置左右必定是有建筑物的. 思路 : 维护一个单调栈,将所有的建筑物和所有的人都放到一起开始算就行,每加入一个人,就 ...
http://acm.hdu.edu.cn/showproblem.php?pid=5033 平面上有n个建筑,每个建筑由(xi,hi)表示,m组询问在某一个点能看到天空的视角范围大小. 维护一个凸包 ...
A histogram is a polygon composed of a sequence of rectangles aligned at a common base line. The rec ...
正解:单调栈 解题报告: 哇生气辽QAQ本来打了半天feel good都快调出来了然后说换题了QAQ(所以可能那题的代码会过一阵子再放上来了QAQ 不过还是大爆手速打了一通拿到首杀了嘻嘻 美滋滋辽 然 ...
新的博客地址 http://lizhug.com
“MVC+Nhibernate+Jquery-EasyUI” 信息发布系统 第四篇(用户管理功能的实现) 一.前三篇的内容是否对您有帮助呢?如果有的话,请您继续关注这篇吧,这篇主要是实现”用户管理“的 ...
CSS 实现的各种球体效果[附在线演示] CSS 可以实现很多你想不到的效果,今天我们来尝试使用 CSS 实现各种球体效果.有两种方法可以实现,第一种是使用大量的元素创建实际的 3D 球体,这种方法有 ...
公共建筑能耗监测平台的GPRS通讯服务器的开发方法分享 在这个文章里面我将用一个实际的案例来分享如何来构建一个能够接受3000+个连接的GPRS通讯服务器软件,这个软件被我认为是一个艺术品,实现周期为 ...
To know what it is, https://wiki.archlinux.org/index.php/Master_Boot_Record For a SD card, dd if=/de ...
啥是SQL注入(SQL Injection) 所谓SQL注入就是把SQL命令插入到表单的输入域或页面请求的查询字符串,欺骗服务器执行恶意的SQL命令.在某些表单中,用户输入的内容直接用来构造 (或影响 ...
Chrome 7月9日刚为Chrome打包的应用提供了强大的访问Google服务例如Google统计.GoogleAPI和Google 钱包的能力,除此之外,还能够使用系统层面的服务包括蓝牙和原生应用 ...
ViewPagerIndicator 的CustomTabPageIndicator 默认是没有Tab选中修改TextView颜色特效的. 可以通过以下方式实现: 新建viewpager_title_ ...
上面学习了线程通过Massage发送字符串消息,Handler接收字符串消息,这样的形式来更新ui,接下来,一起分享怎么把一个对象利用消息机制发送出去,让主线程接收来更新ui. 下面就利用一个服务Se ...
4. <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC " ...