HDU 5033 Building(北京网络赛B题) 单调栈 找规律
做了三天,,,终于a了。。。
| 11724203 | 2014-09-25 09:37:44 | Accepted | 5033 | 781MS | 7400K | 4751 B | G++ | czy |
Building
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 1257 Accepted Submission(s): 358 Special Judge
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.
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).
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
101.3099324740
Case #2:
90.0000000000
Case #3:
78.6900675260
题意:
城市看做二维平面,建筑看做x轴上某个位置为端点的竖着的线段,(xi,hi)表示在x轴xi位置有个高为hi的建筑(线段)。有多次询问,每次问人在某个平地上(x,0)能看到天空的角度。
题解:
维护 相邻两建筑顶(xi,hi)的连线的斜率的绝对值上升 的单调栈。
先把建筑和queries的点全部弄到一起,按xi排个序。然后从左到右来一波得出在某个空地往左看看到最高的是哪个建筑,再反过来来一波。
先按从左到右的情况来说:
维护单调栈,栈里存的是之后的空地可能看到的建筑,容易知这是递减的单调栈。
再思考,如果:

则只用存两边的点,中间那3个肯定看不到了。
如果:

则都要存,因为往右走的时候走着走着,右边第二个就比右边第一个高了,走着走着右边第三个又比右边第二个高了……(这时pop掉栈顶
可见我们存的是相邻两建筑顶(xi,hi)的连线的斜率的绝对值上升 的单调栈。
每看到一个空地,把栈首的不够高的都pop到,只留下那个能看到的最高的,然后把这个建筑加入结果记录中。(记录从这个空地往左看看到的最高的是哪个建筑)
反过来再来一遍。
最后再对询问搞一搞,就完啦。
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<string> #define N 100005
#define M 10000002
#define mod 10000007
//#define p 10000007
#define mod2 100000000
//#define ll long long
//#define LL long long
#define maxi(a,b) (a)>(b)? (a) : (b)
#define mini(a,b) (a)<(b)? (a) : (b) using namespace std; int T;
int n;
int q;
const double pi=*atan(1.0); typedef struct
{
double x;
double h;
double xie;
double xier;
}BB; BB b[N]; typedef struct
{
double x;
double l;
double r;
double ans;
int num;
}QQ; QQ Q[N]; bool cmp1(BB c,BB d)
{
return c.x<d.x;
} bool cmp2(QQ c,QQ d)
{
return c.x<d.x;
} bool cmp3(QQ c,QQ d)
{
return c.num<d.num;
} void ini()
{
int i;
scanf("%d",&n);
for(i=;i<=n;i++){
scanf("%lf%lf",&b[i].x,&b[i].h);
}
sort(b+,b++n,cmp1);
scanf("%d",&q);
for(i=;i<=q;i++){
scanf("%lf",&Q[i].x);
Q[i].num=i;
}
sort(Q+,Q++q,cmp2);
} void solvel()
{
stack <BB> LL;
int i,j; BB te;
double now;
b[].xie=-;
LL.push(b[]);
j=;
for(i=;i<=q;i++){
while(b[j].x<Q[i].x)
{
te=LL.top();
while(LL.size()!= && b[j].h>te.h)
{
LL.pop();
if(LL.size()==) break;
te=LL.top();
} if(LL.size()==){
b[j].xie=-;
LL.push(b[j]);
j++;
continue;
} now=(te.h-b[j].h)/(b[j].x-te.x);
while(LL.size()> && now<te.xie){
LL.pop(); te=LL.top();
now=(te.h-b[j].h)/(b[j].x-te.x);
if(LL.size()<=) break;
}
b[j].xie=now;
LL.push(b[j]);
j++;
} te=LL.top();
Q[i].l=te.h/(Q[i].x-te.x);
LL.pop();
if(LL.size()==){
LL.push(te);
continue;
}
BB pre1=LL.top();
double lte=pre1.h/(Q[i].x-pre1.x);
while(LL.size()!= && lte>Q[i].l)
{
te=pre1;
Q[i].l=lte;
LL.pop();
if(LL.size()==){
// LL.push(te);
break;
}
pre1=LL.top();
lte=pre1.h/(Q[i].x-pre1.x);
}
LL.push(te);
}
} void solver()
{
int i,j;
stack<BB> RR;
BB te;
double now;
b[n].xier=-;
RR.push(b[n]);
j=n-;
for(i=q;i>=;i--){
while(b[j].x>Q[i].x)
{
te=RR.top();
while(RR.size()!= && b[j].h>te.h)
{
RR.pop();
if(RR.size()==) break;
te=RR.top();
} if(RR.size()==){
b[j].xier=-;
RR.push(b[j]);
j--;
continue;
} now=(te.h-b[j].h)/(-b[j].x+te.x);
while(RR.size()> && now<te.xier){
RR.pop(); te=RR.top();
now=(te.h-b[j].h)/(-b[j].x+te.x);
if(RR.size()<=) break;
}
b[j].xier=now;
RR.push(b[j]);
j--;
} te=RR.top();
Q[i].r=te.h/(-Q[i].x+te.x);
RR.pop();
if(RR.size()==){
RR.push(te);
continue;
}
BB pre2=RR.top();
double rte=pre2.h/(-Q[i].x+pre2.x);
while(RR.size()!= && rte>Q[i].r)
{
te=pre2;
Q[i].r=rte;
RR.pop();
if(RR.size()==){
// LL.push(te);
break;
}
pre2=RR.top();
rte=pre2.h/(-Q[i].x+pre2.x);
}
RR.push(te);
}
} void solve()
{
for(int i=;i<=q;i++){
Q[i].ans=(pi-atan(Q[i].l)-atan(Q[i].r))*/pi;
}
} void out()
{
sort(Q+,Q++q,cmp3);
for(int i=;i<=q;i++){
printf("%.10f\n",Q[i].ans);
}
} int main()
{
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
scanf("%d",&T);
for(int cnt=;cnt<=T;cnt++)
// while(T--)
// while(scanf("%d%d",&n,&m)!=EOF)
{
// if(n==0 && m==0) break;
printf("Case #%d:\n",cnt);
ini();
solvel();
solver();
solve();
out();
} return ;
}
HDU 5033 Building(北京网络赛B题) 单调栈 找规律的更多相关文章
- 2015北京网络赛 H题 Fractal 找规律
Fractal Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://hihocoder.com/contest/acmicpc2015beijingo ...
- 2019南昌网络赛-I(单调栈+线段树)
题目链接:https://nanti.jisuanke.com/t/38228 题意:定义一段区间的值为该区间的和×该区间的最小值,求给定数组的最大的区间值. 思路:比赛时还不会线段树,和队友在这题上 ...
- 2015北京网络赛 G题 Boxes bfs
Boxes Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://hihocoder.com/contest/acmicpc2015beijingonl ...
- (中等) Hiho 1232 Couple Trees(15年北京网络赛F题),主席树+树链剖分。
"Couple Trees" are two trees, a husband tree and a wife tree. They are named because they ...
- HDU 6205 2017沈阳网络赛 思维题
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6205 题意:给你n堆牌,原本每一堆的所有牌(a[i]张)默认向下,每次从第一堆开始,将固定个数的牌(b ...
- ACM-ICPC 2018北京网络赛-A题 Saving Tang Monk II-优先队列
做法:优先队列模板题,按步数从小到大为优先级,PASS掉曾经以相同氧气瓶走过的地方就好了 题目1 : Saving Tang Monk II 时间限制:1000ms 单点时限:1000ms 内存限制: ...
- hdu 5442 (ACM-ICPC2015长春网络赛F题)
题意:给出一个字符串,长度是2*10^4.将它首尾相接形成环,并在环上找一个起始点顺时针或逆时针走一圈,求字典序最大的走法,如果有多个答案则找起始点最小的,若起始点也相同则选择顺时针. 分析:后缀数组 ...
- hihoCoder #1388 : Periodic Signal ( 2016 acm 北京网络赛 F题)
时间限制:5000ms 单点时限:5000ms 内存限制:256MB 描述 Profess X is an expert in signal processing. He has a device w ...
- hihocoder 1236(2015北京网络赛 J题) 分块bitset乱搞题
题目大意: 每个人有五门课成绩,初始给定一部分学生的成绩,然后每次询问给出一个学生的成绩,希望知道在给定的一堆学生的成绩比这个学生每门都低或者相等的人数 因为强行要求在线查询,所以题目要求,每次当前给 ...
随机推荐
- 从汇编看c++中的多态
http://www.cnblogs.com/chaoguo1234/archive/2013/05/19/3079078.html 在c++中,当一个类含有虚函数的时候,类就具有了多态性.构造函数的 ...
- Java加腾讯云实现短信验证码功能
一.概要 现如今在日常工作和生活中短信验证码对于我们来说是非常熟悉的,比较常见的注册账号或者交易支付时候,手机会收到一个短信验证码,我们可以通过验证码来有效验证身份,避免一些信息被盗. 验证身份 目前 ...
- 油猴Tampermonkey 全局函数 它的注入函数都在 onload里面,直接写函数 都是内部函数,外部要是调用,就要挂靠到window上
油猴Tampermonkey 全局函数 它的注入函数都在 onload里面,直接写函数 都是内部函数,外部要是调用,就要挂靠到window上 window.like111 = function (){ ...
- Robotium实践之路基于APK创建测试项目
1.重新对包进行签名操作 .启动re-sign.jar文件 .找到相应的APK,拖拽置resigner中 2.创建基于APK测试的测试工程 .新建一个安卓测试项目 .选择this project
- Linux C++/C开发所必需的一系列工具
系统平台下的开发工具.开发环境各有不同.Linux C++/C开发所必需的一系列工具: 1. vi(vim)文本编辑器一个UNIX世界标准的文本编辑器,简约而强大,不论作为开发人员还是系统管理员,熟练 ...
- java在线聊天项目0.9版 实现把服务端接收到的信息返回给每一个客户端窗口中显示功能之客户端接收
客户端要不断接收服务端发来的信息 与服务端不断接收客户端发来信息相同,使用线程的方法,在线程中循环接收 客户端修改后代码如下: package com.swift; import java.awt.B ...
- 字符串数组 输入3个字符串,要求按由小到大的字母顺序输出; 输入n个学生的姓名和学号到字符串数组中,在输入一个姓名,如果班级有该生则返回其信息,否则返回本班无此人
输入3个字符串,要求按由小到大的字母顺序输出 如 输入franch england china,输出结果是china england franch 三个数排序输出,比较三个数的大小怎么做? a=18 ...
- C# 使用Epplus导出Excel [1]:导出固定列数据
C# 使用Epplus导出Excel [1]:导出固定列数据 C# 使用Epplus导出Excel [2]:导出动态列数据 C# 使用Epplus导出Excel [3]:合并列连续相同数据 C# 使用 ...
- sqlite查看所有表名、判断表是否存在,字段名及字段信息
sqlite查看所有表名.判断表是否存在,字段名及字段信息 sqlite查看所有表名及字段名查询table,type 段是'table',name段是table的名字, select name f ...
- NFS基础优化
一.环境 环境接上篇 https://www.cnblogs.com/suffergtf/p/9486250.html 二.参数详解 1.nfsserver端配置参数详解 [root@nfsserve ...