做了三天,,,终于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

Problem 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
 
Source
 
Recommend
hujie   |   We have carefully selected several similar problems for you:  5041 5040 5039 5038 5036 
 
 

题意:

城市看做二维平面,建筑看做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题) 单调栈 找规律的更多相关文章

  1. 2015北京网络赛 H题 Fractal 找规律

    Fractal Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://hihocoder.com/contest/acmicpc2015beijingo ...

  2. 2019南昌网络赛-I(单调栈+线段树)

    题目链接:https://nanti.jisuanke.com/t/38228 题意:定义一段区间的值为该区间的和×该区间的最小值,求给定数组的最大的区间值. 思路:比赛时还不会线段树,和队友在这题上 ...

  3. 2015北京网络赛 G题 Boxes bfs

    Boxes Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://hihocoder.com/contest/acmicpc2015beijingonl ...

  4. (中等) Hiho 1232 Couple Trees(15年北京网络赛F题),主席树+树链剖分。

    "Couple Trees" are two trees, a husband tree and a wife tree. They are named because they ...

  5. HDU 6205 2017沈阳网络赛 思维题

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6205 题意:给你n堆牌,原本每一堆的所有牌(a[i]张)默认向下,每次从第一堆开始,将固定个数的牌(b ...

  6. ACM-ICPC 2018北京网络赛-A题 Saving Tang Monk II-优先队列

    做法:优先队列模板题,按步数从小到大为优先级,PASS掉曾经以相同氧气瓶走过的地方就好了 题目1 : Saving Tang Monk II 时间限制:1000ms 单点时限:1000ms 内存限制: ...

  7. hdu 5442 (ACM-ICPC2015长春网络赛F题)

    题意:给出一个字符串,长度是2*10^4.将它首尾相接形成环,并在环上找一个起始点顺时针或逆时针走一圈,求字典序最大的走法,如果有多个答案则找起始点最小的,若起始点也相同则选择顺时针. 分析:后缀数组 ...

  8. hihoCoder #1388 : Periodic Signal ( 2016 acm 北京网络赛 F题)

    时间限制:5000ms 单点时限:5000ms 内存限制:256MB 描述 Profess X is an expert in signal processing. He has a device w ...

  9. hihocoder 1236(2015北京网络赛 J题) 分块bitset乱搞题

    题目大意: 每个人有五门课成绩,初始给定一部分学生的成绩,然后每次询问给出一个学生的成绩,希望知道在给定的一堆学生的成绩比这个学生每门都低或者相等的人数 因为强行要求在线查询,所以题目要求,每次当前给 ...

随机推荐

  1. 签名ipa,让其它手机也安装

    开发的时候,需要将app让其它人装上测试,虽然通过xcode可以使用编译进去,但是仍显不方便. 网上有个工具, http://code.google.com/p/iresign/ 通过这个工具,使用自 ...

  2. this+call、apply、bind的区别与使用

    http://www.ruanyifeng.com/blog/2018/06/javascript-this.html https://segmentfault.com/a/1190000018017 ...

  3. Web中打印的各种方案参考

    http://blog.csdn.net/chinahuyong/article/details/42527491

  4. Bootstrap历练实例:基本按钮群组

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...

  5. ios lazying load

    初步写一些自己对于lazyload的看法吧.这篇文章主要针对普通view,对于image相关的的懒加载,准备过几天研究一下在写. 懒加载,又称为延迟加载.通常用法,你有一个UITextField类型的 ...

  6. 初涉2-SAT

    2-SAT:有趣的图论模型 什么是2-SAT SAT是适定性(Satisfiability)问题的简称.之所以研究2-sat是因为当k>2时,k-sat问题已经被证明是NPC的了. 2-sat问 ...

  7. 【php】Windows PHP及xdebug安装 安装

    php version 7.0 redis 下载地址 https://pecl.php.net/package/redis 7.0版本的redis不再依赖php_igbinary.dll扩展,可以独立 ...

  8. git commit 含有中文的代码,提示Warnning:Your console font probably doesn't support Unicode.......

    git 提交代码是会遇到以下问题, git commit 代码时提示: Warning: Your console font probably doesn't support Unicode. If ...

  9. jmx_exportter+prometheus+grafana监控hadoop

    0.介绍(摘录自https://www.hi-linux.com/posts/25047.html) 什么是Prometheus? Prometheus是由SoundCloud开发的开源监控报警系统和 ...

  10. 00049_super关键字

    1.子父类中构造方法的调用 (1)在创建子类对象时,父类的构造方法会先执行,因为子类中所有构造方法的第一行有默认的隐式super();语句: (2)格式 调用本类中的构造方法 this(实参列表); ...