题意: 给你 N 楼房, 然后给你m个人站在这些楼房之间, 问看到天空的仰角是多少度

思路: 对于每一个人, 算出左边的凸包, 和右边的凸包, 找出最大斜率点, 算角度即可

(我在线算比较费时, 离线可以省时间)

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const double INF=2e9;
const int maxn = 1e5 + 131;
const double PI = acos(-1.0);
const double eps = 1e-8;
struct Point
{
double x, y;
int pos;
Point(int x = 0,int y = 0): x(x), y(y) {}
//Point(){}
}; int dcmp(double x)
{
if(fabs(x) < eps) return 0;
if(x < 0) return -1;
else return 1;
} typedef Point Vector;
Vector operator + (Vector A, Vector B) { return Vector(A.x+B.x, A.y+B.y); }
Vector operator - (Point A, Point B) { return Vector(A.x-B.x, A.y-B.y); }
bool operator < (Point A, Point B) { return A.x < B.x; }
int Cross(Vector A, Vector B) { return dcmp(A.x*B.y - A.y*B.x); }
double Dot(Vector A, Vector B) { return double(A.x*B.x + A.y*B.y); }
double Length(Vector A) { return sqrt(Dot(A, A)); }
double Angle(Vector A, Vector B) { return acos(Dot(A,B) / Length(A) / Length(B)); } Point p[maxn], ch[maxn];
int PreL[maxn], PreR[maxn]; void ConVexHull(Point *p, int n, Point *ch)
{
int m = 0;
PreL[0] = 0;
for(int i = 0; i < n; ++i) {
while(m > 1 && dcmp(Cross(ch[m-1] - ch[m-2], p[i]-ch[m-2]) > 0)) m--;
ch[m++] = p[i];
if(i) PreL[i] = ch[m-2].pos;
}
m = 0;
PreR[n-1] = n-1;
for(int i = n-1; i >= 0; --i) {
while(m > 1 && dcmp(Cross(ch[m-1] - ch[m-2], p[i]-ch[m-2]) < 0)) m--;
ch[m++] = p[i];
if(n-1-i) PreR[i] = ch[m-2].pos;
}
}
int lb(double xx,int n)
{
int left = 0, right = n;
p[n].x = INF;
while(left < right)
{
int mid=(left+right)>>1;
if(xx<p[mid].x)
right=mid;
else
left=mid+1;
}
return left-1;
} int main()
{
int t;
scanf("%d",&t);
for(int kase = 1; kase <= t; ++kase)
{
int n;
scanf("%d",&n);
for(int i = 0; i < n; ++i)
{
scanf("%lf%lf", &p[i].x, &p[i].y);
}
sort(p,p+n);
for(int i = 0; i < n; ++i) p[i].pos = i;
ConVexHull(p,n,ch);
/*for(int i = 0; i < n; ++i)
cout << PreL[i] << " ";
cout <<endl;
for(int i = 0; i < n; ++i)
cout << PreR[i] << " ";
cout <<endl;*/
int Q; double pos;
scanf("%d",&Q);
printf("Case #%d:\n",kase);
while(Q--)
{
scanf("%lf",&pos);
int lll = lb(pos,n);
int rrr = lll + 1;
Point New(pos, 0);
/*cout << New.x << " " << New.y <<endl;
cout << p[lll].x << " " << p[lll].y << endl;
cout << p[rrr].x << " " << p[rrr].y << endl;
cout << "***********************\n";
cout << p[PreL[lll]].x << " " << p[PreL[lll]].y <<endl;
cout << p[n-PreR[rrr]-1].x << " " << p[n-1-PreR[rrr]].y <<endl;*/
Vector L, R;
while(dcmp(Cross(p[lll]-New, p[PreL[lll]]-New) < 0)) lll = PreL[lll];
L = p[lll]-New; while(dcmp(Cross(p[rrr]-New, p[PreR[rrr]]-New) > 0)) rrr = PreR[rrr];
R = p[rrr] - New; //cout << "L : \n" << L.x << " " << L.y<< endl;
//cout << "R : \n" << R.x << " " << R.y<< endl;
double Degree = fabs(Angle(L,R)*180 / PI);
printf("%.10f\n",Degree);
}
}
}

  

HDU 5033的更多相关文章

  1. HDU 5033 Building(单调栈)

    HDU 5033 Building(单调栈) 题目链接http://acm.hdu.edu.cn/showproblem.php?pid=5033 Description Once upon a ti ...

  2. hdu 5033 buiding(单调栈)

    hdu 5033 buiding(单调栈) 某年某月某天,马特去了一个小镇.这个小镇如此狭窄,以至于他可以把小镇当作一个枢纽.在镇上有一些摩天大楼,其中一栋位于xi,高度为hi.所有的摩天大楼位于不同 ...

  3. HDU 5033 Building

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5033 解题报告:在一条x轴上有n个建筑物,每个建筑物有一个高度h,然后现在有q次查询,查询的内容是假设 ...

  4. hdu 5033 模拟+单调优化

    http://acm.hdu.edu.cn/showproblem.php?pid=5033 平面上有n个建筑,每个建筑由(xi,hi)表示,m组询问在某一个点能看到天空的视角范围大小. 维护一个凸包 ...

  5. hdu - 5033 - Building(单调栈)

    题意:N 幢楼排成一列(1<=N<=10^5),各楼有横坐标 xi(1<=xi<=10^7) 以及高度 hi(1<=hi<=10^7),在各楼之间的Q个位置(1&l ...

  6. HDU 5033 Building(北京网络赛B题) 单调栈 找规律

    做了三天,,,终于a了... 11724203 2014-09-25 09:37:44 Accepted 5033 781MS 7400K 4751 B G++ czy Building Time L ...

  7. hdu 5033 单调栈 ****

    看出来是单调栈维护斜率,但是不会写,2333,原来是和询问放在一起的 #include <iostream> #include <cstdio> #include <cs ...

  8. HDU 5033 Building --离线+单调栈

    题意:给一些建筑物,x表示横坐标,h表示高度,然后查询某些坐标x,问从该点看向天空的最大张角是多大. 解法:离线操作,读入所有数据,然后按x升序排序,对每一个查询的x,先从左到右,依次添加x坐标小于x ...

  9. HDU 5033 (单调栈维护凸包) Building

    题意: 一个人在x轴上,他的左右两侧都有高楼,给出楼的横坐标Xi和高度Hi还有人的位置pos,求人所能看到的天空的最大角度. 分析: 将建筑物和人的位置从左到右排序,对于每个位置利用栈求一次人左边建筑 ...

  10. HDU 5033 Building(单调栈维护凸包)

    盗张图:来自http://blog.csdn.net/xuechelingxiao/article/details/39494433 题目大意:有一排建筑物坐落在一条直线上,每个建筑物都有一定的高度, ...

随机推荐

  1. SQL Server进阶 遍历表的几种方法

    https://www.cnblogs.com/mcgrady/p/4182486.html

  2. Sqlserver远程过程调用失败

    这种情况一般是由于有高版本的SqlServer导致的,网上有删除Loaldb之类的建议,这样其实不太好,回头用高版本数据库的话还得装回来.其实可以通过计算机管理->服务和应用程序进行设置,用下面 ...

  3. 大规模数据导入和导出(mysql)

    测试数据2.5G,共有数据9427567条.用的mysql的large服务器的配置.load 一次需要大概10分钟左右.建的表用的是MYISAM,调整了几个session的参数值 SET SESSIO ...

  4. centos6.5配置redis服务 很好用谢谢

    1.下载Redis3.2.5安装包               wget http://download.redis.io/releases/redis-3.2.5.tar.gz   2.解压.编译. ...

  5. 【python小练】0002

    第 0002 题:将 0001 题生成的 200 个激活码(或者优惠券)保存到 MySQL 关系型数据库中. . . .(一脸懵逼) Python访问数据库:(廖雪峰python教程) 1. SQLi ...

  6. python的进程/线程/协程

    1.python的多线程 多线程就是在同一时刻执行多个不同的程序,然而python中的多线程并不能真正的实现并行,这是由于cpython解释器中的GIL(全局解释器锁)捣的鬼,这把锁保证了同一时刻只有 ...

  7. 通过命令窗口控制mysql服务的启动与停止

    mysql服务的启动: 以管理员的身份运行cmd命令窗口,输入命名 net start mysql 如果不是以管理员的身份运行cmd,会提示如下错误 mysql服务的停止: 以管理员的身份运行cmd命 ...

  8. Python 爬虫五 进阶案例-web微信登陆与消息发送

    首先回顾下网页微信登陆的一般流程 1.打开浏览器输入网址 2.使用手机微信扫码登陆 3.进入用户界面 1.打开浏览器输入网址 首先打开浏览器输入web微信网址,并进行监控: https://wx.qq ...

  9. P1880 [NOI1995]石子合并(区间DP)

    题目链接:https://www.luogu.org/problemnew/show/P1880 题目大意:中文题目 具体思路:和上一篇的思路是差不多的,也是对于每一个小的区间进行处理,然后再归并到大 ...

  10. 20165337第七周实验报告《Java面向对象程序设计》

    实验报告封面 实验内容及步骤 实验一.实现百分制成绩转成"优.良.中.及格.不及格"五级制成绩的功能 代码 public class MyUtil{ public static S ...