HDU 5033 Building
2015-09-09 15:56
549 查看
题目大意:给出n个高楼的位置(可看做垂直x轴的线段) 有q次查询 每次查询一个x坐标 求在此处的能看到天空的角度范围
由于查询次数q有10的5次方 n也有10的5次方 x坐标10的7次方 很难想到预先处理好 然后O(1)查询的处理方式 所以可以尝试用离线 预先把查询的坐标 以(x,0)存入 高楼以(x,h)来存
首先要以x排个序 首先 如果你每个查询点 左右的暴力找 这样肯定太慢 但你不难发现一条规律 每个点在右面找到的那个斜率最高点设为A(即从查询点来看 这个大楼是最高的)那么这个点有什么特征的 首先 很容易的推出 点A 右面比A低的肯定不行 同理A左面(和查询点之间)也不存在比A高的 当然这样还是不够的 因为极限数据 最高复杂度依然会T 所以我们继续推 A和查询点直接的点 应该是构成一条 x²一样曲线的(其实是折线) 这样才能做到在A点斜率最大 而A右面的点应该是 根号x曲线 一样的 这样 不难得到
A是一个凸包上的点 (如果这都没想到凸包 说明你没透彻理解凸包) 查询点加进来之后(从右往左扫时) A和查询点之间的点会被删掉 所以我们扫到每个查询点时 和凸包上的上一个点 计算一下即可 从左到右扫两遍 复杂度O(nlogn)
由于查询次数q有10的5次方 n也有10的5次方 x坐标10的7次方 很难想到预先处理好 然后O(1)查询的处理方式 所以可以尝试用离线 预先把查询的坐标 以(x,0)存入 高楼以(x,h)来存
首先要以x排个序 首先 如果你每个查询点 左右的暴力找 这样肯定太慢 但你不难发现一条规律 每个点在右面找到的那个斜率最高点设为A(即从查询点来看 这个大楼是最高的)那么这个点有什么特征的 首先 很容易的推出 点A 右面比A低的肯定不行 同理A左面(和查询点之间)也不存在比A高的 当然这样还是不够的 因为极限数据 最高复杂度依然会T 所以我们继续推 A和查询点直接的点 应该是构成一条 x²一样曲线的(其实是折线) 这样才能做到在A点斜率最大 而A右面的点应该是 根号x曲线 一样的 这样 不难得到
A是一个凸包上的点 (如果这都没想到凸包 说明你没透彻理解凸包) 查询点加进来之后(从右往左扫时) A和查询点之间的点会被删掉 所以我们扫到每个查询点时 和凸包上的上一个点 计算一下即可 从左到右扫两遍 复杂度O(nlogn)
#include<iostream> #include<cstdio> #include<cstring> #include<cctype> #include<cmath> #include<vector> #include<queue> #include<map> #include<algorithm> #include<set> #define scnaf scanf #define cahr char #define bug puts("bugbugbug"); using namespace std; typedef long long ll; const int mod=1000000007; const int maxn=2e5+500; const int inf=1e9+10000; #define pai acos(-1.0) double ans[maxn]; int n; struct Point { double x,y; int id; Point(double x=0,double y=0,int id=0):x(x),y(y),id(id) {} } p[maxn],ch[maxn]; Point operator - (Point A,Point B) { return Point(A.x - B.x, A.y - B.y , 0); } bool operator < (const Point& a, const Point& b) { return a.x<b.x; } double Cross(Point A,Point B) { return A.x*B.y-A.y*B.x; } double jisuan(Point A,Point B) { return atan( fabs( (A.y-B.y) / (A.x-B.x) ) ) * 180 / pai; } bool cmp(Point A,Point B) { return A.x>B.x; } void go() { sort(p,p+n); int m=0; for(int i=0; i<n; i++) { if(i&&p[i].x==p[i-1].x) { ans[p[i].id]=ans[p[i-1].id]; continue; } while(m>1 && Cross(ch[m-1]-ch[m-2] ,p[i]-ch[m-2]) >= 0) m--; if(p[i].id!=-1) { double now=jisuan(p[i],ch[m-1]); ans[p[i].id]-=now; } ch[m++]=p[i]; } m=0; for(int i=n-1; i>=0; i--) { if(i!=n-1&&p[i].x==p[i+1].x) { ans[p[i].id]=ans[p[i+1].id]; continue; } while(m>1 && Cross(p[i]-ch[m-2],ch[m-1]-ch[m-2]) >= 0) m--; if(p[i].id!=-1) { double now=jisuan(p[i],ch[m-1]); ans[p[i].id]-=now; } ch[m++]=p[i]; } } int main() { int T_T,test=1; scanf("%d",&T_T); while(T_T--) { int q; scanf("%d",&n); for(int i=0; i<n; i++) { scanf("%lf%lf",&p[i].x,&p[i].y); p[i].id=-1; } scanf("%d",&q); for(int j=0; j<q; j++) { scanf("%lf",&p[n+j].x); p[n+j].y=0; p[n+j].id=j; ans[j]=180; } n+=q; go(); printf("Case #%d:\n",test++); for(int i=0; i<q; i++) printf("%.10f\n",ans[i]); } }
相关文章推荐
- 修改easyui日期控件只显示年月,并且只能选择年月
- 进程pid,ppid;进程uid,euid;用户uid,guid
- jeasyui在页面显式创建dialog并兼容IE8
- iOS 利用NSNumber和NSValue将非OC对象类型数据存放到集合
- 初学require.js
- 玩转EasyUI之Dialog
- UILabel显示多行文本,字体设置
- 1099. Build A Binary Search Tree (30)
- UIBezierPath贝塞尔弧线常用方法记
- iosUI—CALayer
- Android开发——异步更新UI的四种方式
- UISearchBar 背景 边框设置
- View requires API level 11 (current min is 8): <CalendarView>
- A potentially dangerous Request.Path value was detected from the client 异常
- 使用代码和storyboard分别创建UITabBarController
- The differences between String, StringBuffer and StringBuilder
- UIScrollView 滚动停止的时候一次调用此方法
- 【Android UI】 Shape详解 (GradientDrawable)
- UIView的layoutSubviews和drawRect方法何时调用
- UEditor扩展又拍云图片存储功能实践