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

最新文章

  1. C# 多种方式发送邮件(附帮助类)
  2. Happy New Year 2016
  3. SWFUpload
  4. 用户视角 vs 系统视角 看性能
  5. Gradle学习系列之八——构建多个Project
  6. 【转】线程、Thread类和线程终止
  7. 用C#编写游戏脚本
  8. SQL2008-功能设置
  9. libthrift0.9.0解析(一)之TServer
  10. javascript第二课练习
  11. php分页实例附代码
  12. java注解入门(含源码下载)
  13. Java ClassLoader 原理分析
  14. Tomcat配置(二):tomcat配置文件server.xml详解和部署简介
  15. [POJ 3635] Full Tank?
  16. 移除 iview的Input组件默认background效果
  17. Kali 2.0 下 Metasploit 初始化配置
  18. Navicat安装及简单使用
  19. MyBatis源码分析-基础支持层反射模块Reflector/ReflectorFactory
  20. PAT 1035 Password

热门文章

  1. NASM 之 helloworld1
  2. C# 队列Queue
  3. Bootstrap历练实例:分页状态
  4. Log4J的配置与使用详解
  5. awk日志分割
  6. java在线聊天项目1.2版 ——开启多个客户端,分别实现数据库注册和登录功能后,成功登陆则登录框消失,好友列表窗出现
  7. Python从文件中读取数据(2)
  8. Educational Codeforces Round 32:E. Maximum Subsequence(Meet-in-the-middle)
  9. python基础——14(shelve/shutil/random/logging模块/标准流)
  10. BZOJ 2508: 简单题