做了三天,,,终于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. NSCopying协议和copy方法

    不是所有的对象都支持 copy需要继承NSCopying 协议(实现 copyWithZone: 方法)同样,需要继承NSMutableCopying 协议才可以使用mutableCopy(实现 mu ...

  2. VGG16学习笔记

    转载自:http://deanhan.com/2018/07/26/vgg16/ 摘要 本文对图片分类任务中经典的深度学习模型VGG16进行了简要介绍,分析了其结构,并讨论了其优缺点.调用Keras中 ...

  3. js 监听页面url锚点变化 window.onpopstate

    window.onpopstate = function (event) { if (location.href.indexOf('#') == -1) { location.reload(); } ...

  4. Python 解压序列、可迭代对象并赋值给多个变量

    Python数据结构和类型 1.1 解压序列赋值给多个变量 现在有一个包含N个元素的元组或者是序列,怎样将它里面的值解压后同时赋值给N个变量? 解决思路:先通过简单的解压赋值给多个变量,前提是变量的数 ...

  5. servlet多文件上传(带进度条)

    需要commons-fileupload-1.3.jar和commons-io-2.4.jar的支持 页面效果:(图片文件都可以) (1)进度标识类 public class UploadStatus ...

  6. HTML5<picture>元素

    HTML5<picture>元素可以设置多张图片 <!DOCTYPE html><html><head><meta http-equiv=&quo ...

  7. 大数据学习系列之Hadoop、Spark学习线路(想入门大数据的童鞋,强烈推荐!)

    申明:本文出自:http://www.cnblogs.com/zlslch/p/5448857.html(该博客干货较多) 1 Java基础: 视频方面:          推荐<毕向东JAVA ...

  8. Mac 输入法小技巧

    相信使用Mac的朋友第一次使用Mac首先要考虑的就是输入法的问题,现在越来越多的第三方输入法都开始支持Mac平台,是否有同学仍然执着于看似“不符”国人习惯用法的OS X自带拼音输入法呢?自带的拼音输入 ...

  9. shell中test的使用

    #/secondin/secondfirstshecho “please enter two numseconder”read firstread secondif test $first -eq $ ...

  10. 创建安卓模拟器的两种方式及常用Android命令介绍

    创建安卓模拟器有以下两种方式: 1>通过图形界面创建,在Eclipse中单击Windows->Android Virtual Device Manager启动图形界面窗口 2>如果用 ...