http://acm.hdu.edu.cn/showproblem.php?pid=5033
Building Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 303 Accepted Submission(s): 85 Special Judge
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
Case #1: 101.3099324740 Case #2: 90.0000000000 Case #3: 78.6900675260
题意:
给出N幢摩天大楼的位置和高度,有Q次查询,问在某点处能看见天空的角度范围。
分析:
一开始的想法是维护一个单调栈,首先离线数据并排序排序,然后左右扫两边。单调栈内大楼的高度要递减,然后判断栈顶元素是否比它的前一个更优,如果不是则出栈。但是如果栈顶元素比它前一个优,并不能保证是全局最优的。
正确的维护方法是保证单调栈内的大楼高度递减,而且要使得这些大楼的最高点构成一个类似凸包的形状,或者说是凸包的一部分,然后再判断栈顶元素和它前一个比是否更优,如果不是则出栈。这样最后的栈顶元素就是待查询点在某方向的视角最大范围,记录下这个方向向量即可,最后角度只要求两向量间的夹角即可。
(ugly code,maybe I could attend ioccc)
/* * * Author : fcbruce * * Date : 2014-09-21 13:07:59 * */ #include <cstdio> #include <iostream> #include <sstream> #include <cstdlib> #include <algorithm> #include <ctime> #include <cctype> #include <cmath> #include <string> #include <cstring> #include <stack> #include <queue> #include <list> #include <vector> #include <map> #include <set> #define sqr(x) ((x)*(x)) #define LL long long #define itn int #define INF 0x3f3f3f3f #define PI 3.1415926535897932384626 #define eps 1e-10 #ifdef _WIN32 #define lld "%I64d" #else #define lld "%lld" #endif #define maxm 100010 #define maxn 100010 using namespace std; struct node { double x,h; bool operator < (const node &n)const { return x<n.x; } }sky[maxn]; struct __q { double x; int h; bool operator < (const __q &q)const { return x<q.x; } }q[maxm]; inline double dot(const pair<double,double> &v1,const pair<double,double> &v2) { return v1.first*v2.first+v1.second*v2.second; } inline double len(const pair<double,double> &v) { return sqrt(sqr(v.first)+sqr(v.second)); } pair<double,double> v_l[maxn],v_r[maxn]; int st[maxn]; int main() { #ifdef FCBRUCE freopen("/home/fcbruce/code/t","r",stdin); #endif // FCBRUCE int T_T,__=0; scanf("%d",&T_T); while (T_T--) { int n,m; scanf("%d",&n); for (int i=0;i<n;i++) scanf("%lf%lf",&sky[i].x,&sky[i].h); sort(sky,sky+n); scanf("%d",&m); for (int i=0;i<m;i++) { scanf("%lf",&q[i].x); q[i].h=i; } sort(q,q+m); for (int i=0,j=0,top=-1;i<m;i++) { while (j<n && sky[j].x<q[i].x) { while (top>-1 && sky[j].h>sky[st[top]].h-eps) top--; while (top>0 && (sky[st[top]].h-sky[j].h)*(sky[st[top]].x-sky[st[top-1]].x)< (sky[st[top-1]].h-sky[st[top]].h)*(sky[j].x-sky[st[top]].x)+eps) top--; st[++top]=j++; while (top>0 && sky[st[top]].h*(q[i].x-sky[st[top-1]].x)<sky[st[top-1]].h*(q[i].x-sky[st[top]].x)+eps) top--; } while (top>0 && sky[st[top]].h*(q[i].x-sky[st[top-1]].x)<sky[st[top-1]].h*(q[i].x-sky[st[top]].x)+eps) top--; v_l[q[i].h]=make_pair(sky[st[top]].x-q[i].x,sky[st[top]].h); } for (int i=m-1,j=n-1,top=-1;i>=0;i--) { while (j>=0 && sky[j].x>q[i].x) { while (top>-1 && sky[j].h>sky[st[top]].h-eps) top--; while (top>0 && (sky[st[top]].h-sky[j].h)*(sky[st[top-1]].x-sky[st[top]].x)< (sky[st[top-1]].h-sky[st[top]].h)*(sky[st[top]].x-sky[j].x)+eps) top--; st[++top]=j--; while (top>0 && sky[st[top]].h*(sky[st[top-1]].x-q[i].x)<sky[st[top-1]].h*(sky[st[top]].x-q[i].x)+eps) top--; } while (top>0 && sky[st[top]].h*(sky[st[top-1]].x-q[i].x)<sky[st[top-1]].h*(sky[st[top]].x-q[i].x)+eps) top--; v_r[q[i].h]=make_pair(sky[st[top]].x-q[i].x,sky[st[top]].h); } printf("Case #%d:\n",++__); for (int i=0;i<m;i++) printf("%.10f\n",acos(dot(v_l[i],v_r[i])/(len(v_r[i])*len(v_l[i])))*180/PI); } return 0; }
原文地址:http://blog.csdn.net/u012965890/article/details/39456117