这个是2014年北京网络赛的1002 。
只是在直接暴力的基础上加了个预处理,如果数据卡的严的话,估计还是TLE。。
不是正解,也就不再多解释了。搞明白时会再补充。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include <queue>
#include<cmath>
#include<cstring>
#define maxn 100000
#define M_PI acos(-1)
using namespace std;
struct Point
{
double x;
double h;
int num;
bool operator < (const Point a)const
{
return h>a.h;
}
};
double angle(Point a,Point b,double xx)
{
// double ma_x = b.x - xx;
// double ma_y = b.h - 0;
// double mb_x = a.x- xx;
// double mb_y = a.h - 0;
// double v1 = (ma_x * mb_x) + (ma_y * mb_y);
// double ma_val = sqrt(ma_x*ma_x + ma_y*ma_y);
// double mb_val = sqrt(mb_x*mb_x + mb_y*mb_y);
// double cosM = v1 / (ma_val*mb_val);
// return acos(cosM) * 180 / M_PI;
return(M_PI-(atan(a.h/(xx-a.x))+atan(b.h/(b.x-xx))))*180*1.0/M_PI;
}
Point p[maxn];
int n;
int le[maxn], ri[maxn];
int cmp(const Point & a, const Point & b)
{
return a.x<b.x;
}
void solve()
{
for(int i=0; i<n; i++)
p[i].num=i;
priority_queue<Point> q;
while(!q.empty())q.pop();
q.push(p[n-1]);
ri[n-1]=-1;
for(int i=n-2; i>=0; i--)
{
while(p[i].h>=q.top().h && !q.empty())
q.pop();
if(q.empty())
ri[i]=-1;
else ri[i]=q.top().num;
q.push(p[i]);
}
while(!q.empty())
q.pop();
q.push(p[0]);
le[0]=-1;
for(int i=1; i<n; i++)
{
while(p[i].h>=q.top().h && !q.empty())
q.pop();
if(q.empty())
le[i]=-1;
else le[i]=q.top().num;
q.push(p[i]);
}
}
int find(double val)
{
int x=0;
int y=n;
while(x<y)
{
int m=x+(y-x)/2;
if(p[m].x>=val) y=m;
else x=m+1;
}
return x;
}
int main()
{
int t;
scanf("%d",&t);
for(int kase =1; kase<=t; kase++)
{
scanf("%d",&n);
for(int i=0; i<n; i++)
{
scanf("%lf%lf",&p[i].x,&p[i].h);
}
sort(p,p+n, cmp);
solve();
int q;
double xx;
scanf("%d",&q);
printf("Case #%d:\n",kase);
for(int k=0; k<q; k++)
{
int pos=0;
scanf("%lf",&xx);
pos = find(xx);
double ans=360;
double o=angle(p[pos-1],p[pos],xx);
int xl=pos-1,xr=pos;
for(int i=pos; i!=-1; i=ri[i])
{
o=angle(p[xl],p[i],xx);
if(ans>o)
{
xr=i;
ans=o;
}
}
for(int i=pos-1; i!=-1; i=le[i])
ans=min(ans, angle(p[i],p[xr],xx));
printf("%.10lf\n",ans);
}
}
return 0;
}