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 不过还是大爆手速打了一通拿到首杀了嘻嘻 美滋滋辽 然 ...
随机推荐
- 《.NET 编程结构》专题汇总
<.NET 编程结构>专题汇总 前言 掌握一门技术,首要的是掌握其基础. 笔者从事.NET相关开发多年,也非常喜欢.NET,多年来也积累了很多相关的资料,在此将一些基础性的 ...
- TFS的安装
TFS的安装 本系列的实例将采用TFS 2012+Sql Server2012编写. TFS的完整版本安装最好是在Windows server2008 64位以上版本中,其包括64位的SQL SERV ...
- ajax简单后台交互
ajax简单后台交互 1,扯淡 单身的生活,大部分时间享受自由,小部分时间忍受寂寞. 生活有时候,其实蛮苦涩,让人难以下咽.那些用岁月积累起来的苦闷,无处宣泄,在自己的脑海里蔓延成一片片荆棘,让你每每 ...
- poj 3897 Maze Stretching 二分+A*搜索
题意,给你一个l,和一个地图,让你从起点走到终点,使得路程刚好等于l. 你可以选择一个系数,把纵向的地图拉伸或收缩,比如你选择系数0.5,也就是说现在上下走一步消耗0.5的距离,如果选择系数3,也就是 ...
- api 和 abi的区别
156down vote API: Application Program Interface This is the set of public types/variables/functions ...
- mybatis判断list为空
在传入的map或者对象里面存在一个list,此时想要判断list是否为空,可以 <if test="spids.size()>0 " > and SPid not ...
- python数据类型以及模块的含义
print(sys.path) #打印环境变量 print(sys.argv) #打印相对路径 print(sys.argv[1]) #打印对应的参数 1.在python最上有时候会导入os模块,表示 ...
- Dos.ORM Select查询 自定义列
自定义列 .Select( p = >new{ test = p.id}) // 同sql 列名 as 新列名 如下是 自己在写代码的例子,查询,分页,where条件,排序 var where ...
- Docker集群实验环境布署--swarm【5 容器启动组件--node】
10.40.100.143 docker-node0.venic.com 10.40.100.144 docker-node1.venic.com 原用swarm镜像 直接启动 1 ...
- Object-Widgets-Quick 构造树
Object Tree 当以某个QObject为父类创建一个QObject时, 它会被添加到该父类的children列表中. 析构时, QObjet 会首先检查自己的children, 依次析构, 然 ...
题目链接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 不过还是大爆手速打了一通拿到首杀了嘻嘻 美滋滋辽 然 ...
<.NET 编程结构>专题汇总 前言 掌握一门技术,首要的是掌握其基础. 笔者从事.NET相关开发多年,也非常喜欢.NET,多年来也积累了很多相关的资料,在此将一些基础性的 ...
TFS的安装 本系列的实例将采用TFS 2012+Sql Server2012编写. TFS的完整版本安装最好是在Windows server2008 64位以上版本中,其包括64位的SQL SERV ...
ajax简单后台交互 1,扯淡 单身的生活,大部分时间享受自由,小部分时间忍受寂寞. 生活有时候,其实蛮苦涩,让人难以下咽.那些用岁月积累起来的苦闷,无处宣泄,在自己的脑海里蔓延成一片片荆棘,让你每每 ...
题意,给你一个l,和一个地图,让你从起点走到终点,使得路程刚好等于l. 你可以选择一个系数,把纵向的地图拉伸或收缩,比如你选择系数0.5,也就是说现在上下走一步消耗0.5的距离,如果选择系数3,也就是 ...
156down vote API: Application Program Interface This is the set of public types/variables/functions ...
在传入的map或者对象里面存在一个list,此时想要判断list是否为空,可以 <if test="spids.size()>0 " > and SPid not ...
print(sys.path) #打印环境变量 print(sys.argv) #打印相对路径 print(sys.argv[1]) #打印对应的参数 1.在python最上有时候会导入os模块,表示 ...
自定义列 .Select( p = >new{ test = p.id}) // 同sql 列名 as 新列名 如下是 自己在写代码的例子,查询,分页,where条件,排序 var where ...
10.40.100.143 docker-node0.venic.com 10.40.100.144 docker-node1.venic.com 原用swarm镜像 直接启动 1 ...
Object Tree 当以某个QObject为父类创建一个QObject时, 它会被添加到该父类的children列表中. 析构时, QObjet 会首先检查自己的children, 依次析构, 然 ...