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 不过还是大爆手速打了一通拿到首杀了嘻嘻 美滋滋辽 然 ...
随机推荐
- PHP 数组拼接成字符串
PHP[知识分享] 数组拼接成字符串 <?php // 格式: [二维数组] Array ( [0] => Array ( [topicid] => 1 ) [1] => Ar ...
- 对象转Json序列化
C#--对象转Json序列化 前言 最近在研究Android项目,其中涉及到Android中解析Json数据的问题,需要模拟网络中传递Json数据的模式,因为以前是.net的工程师,所以想着从.net ...
- JBoss + EJB3 + MySql : 开发第一个EJB
JBoss开发Bean并不困难,而对于不知道的人来说,数据库配置才是比较棘手的问题.现在我们就来一步一步开发一个EJB3 + MySql的Bean. 一.MySql数据库的配置 1. 配置数据源 在 ...
- 写一些脚本的心得总结系列第4篇-------从数据库同步到redis
5.从数据库同步到redis的. redis把数据放内存里,读取都非常方便,也提供了远超memcache的丰富数据结构.下面我举2个例子,比如1)把数据从数据库写入到redis: <?php $ ...
- swift 动态获取label宽度或高度
func getLabHeigh(labelStr:String,font:UIFont,width:CGFloat) -> CGFloat { let statusLabelText: NSS ...
- 【Zookeeper】源码分析之持久化--FileTxnSnapLog
一.前言 前面分析了FileSnap,接着继续分析FileTxnSnapLog源码,其封装了TxnLog和SnapShot,其在持久化过程中是一个帮助类. 二.FileTxnSnapLog源码分析 2 ...
- Java排序方法sort的使用详解
对数组的排序: //对数组排序 public void arraySort(){ int[] arr = {1,4,6,333,8,2}; Arrays.sort(arr);//使用java.util ...
- HTML target 属性
定义和用法 <a> 标签的 target 属性规定在何处打开链接文档. 如果在一个 <a> 标签内包含一个 target 属性,浏览器将会载入和显示用这个标签的 href 属性 ...
- 360回归A股,周鸿祎来给BAT和小米添堵了
排着队回国内上市的公司名单里,终于多了奇虎360的名字. 奇虎360今天宣布,公司董事会收到了来自董事长周鸿祎.中信证券及其附属公司.Golden Brick Capital Private Equi ...
- InnoDB引擎数据存放位置
InnoDB引擎的mysql数据存放位置 采用InnoDB引擎的数据库创建表后,会在mysql数据存放目录下生成一个和数据库名相同的目录.该目录下包涵一个db.opt文件和该库下所有表同名的frm文件 ...
题目链接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 不过还是大爆手速打了一通拿到首杀了嘻嘻 美滋滋辽 然 ...
PHP[知识分享] 数组拼接成字符串 <?php // 格式: [二维数组] Array ( [0] => Array ( [topicid] => 1 ) [1] => Ar ...
C#--对象转Json序列化 前言 最近在研究Android项目,其中涉及到Android中解析Json数据的问题,需要模拟网络中传递Json数据的模式,因为以前是.net的工程师,所以想着从.net ...
JBoss开发Bean并不困难,而对于不知道的人来说,数据库配置才是比较棘手的问题.现在我们就来一步一步开发一个EJB3 + MySql的Bean. 一.MySql数据库的配置 1. 配置数据源 在 ...
5.从数据库同步到redis的. redis把数据放内存里,读取都非常方便,也提供了远超memcache的丰富数据结构.下面我举2个例子,比如1)把数据从数据库写入到redis: <?php $ ...
func getLabHeigh(labelStr:String,font:UIFont,width:CGFloat) -> CGFloat { let statusLabelText: NSS ...
一.前言 前面分析了FileSnap,接着继续分析FileTxnSnapLog源码,其封装了TxnLog和SnapShot,其在持久化过程中是一个帮助类. 二.FileTxnSnapLog源码分析 2 ...
对数组的排序: //对数组排序 public void arraySort(){ int[] arr = {1,4,6,333,8,2}; Arrays.sort(arr);//使用java.util ...
定义和用法 <a> 标签的 target 属性规定在何处打开链接文档. 如果在一个 <a> 标签内包含一个 target 属性,浏览器将会载入和显示用这个标签的 href 属性 ...
排着队回国内上市的公司名单里,终于多了奇虎360的名字. 奇虎360今天宣布,公司董事会收到了来自董事长周鸿祎.中信证券及其附属公司.Golden Brick Capital Private Equi ...
InnoDB引擎的mysql数据存放位置 采用InnoDB引擎的数据库创建表后,会在mysql数据存放目录下生成一个和数据库名相同的目录.该目录下包涵一个db.opt文件和该库下所有表同名的frm文件 ...