当初比赛的时候本来想着单调栈来着,但是不知道维护的是什么?因为对于查询的点不同的话他们的斜率也会跟着变化,所以后边就没写。
现在知道将查询的各个点也当成一个高度为0的楼,只需维护对于每一栋楼楼顶上的点的斜率。要维护一个从栈底到栈顶斜率一直递增的单调栈就行,那么的话对于他的一个端点就是栈顶元素。因为栈顶元素是斜率最大的。
PS :非常巧妙,当初怎们没有想到。
#include<bits/stdc++.h>
using namespace std;
#define clr(x,y) memset(x,y,sizeof x)
const int maxn = 3e5 + 10;
struct Node
{
bool operator < (Node t)
{
return x < t.x;
}
double x ,y;
int pos;
int L,R;
}a[maxn];
bool vis[10000010];
int st[maxn];
double get(Node x,Node y)
{
return (x.y - y.y) / fabs(y.x - x.x);
}
bool check(Node x,Node y,Node z)
{
return get(x,y) > get(y,z);
}
double dis(Node x,Node y)
{
return sqrt((x.x - y.x) * (x.x - y.x) + (x.y - y.y) * (x.y - y.y));
}
double fun(Node x,Node y,Node z)
{
double a = dis(x,z),b = dis(y,z),c = dis(x,y);
return acos((a * a + b * b - c * c)/(2 * a * b));
}
double ans[maxn];
int main()
{
int Tcase;scanf("%d",&Tcase);
for(int ii = 1;ii <= Tcase;ii ++)
{
int n,m;scanf("%d",&n);
clr(vis,false);
for(int i = 1; i <= n;i ++)
{
scanf("%lf%lf",&a[i].x,&a[i].y);
a[i].pos = i;
vis[int(a[i].x)] = false;
}
scanf("%d",&m);
for(int i = 1;i <= m;i ++)
{
double x;scanf("%lf",&x);
vis[int(x)] = true;
a[i + n] = (Node){x,0,i};
}
printf("Case #%d:\n",ii);
n = n + m;
sort(a + 1,a + n + 1);
// for(int i = 1; i <= n;i ++)cout << a[i].x << " " ;puts(" ---");
int cnt = 0;st[++ cnt] = 1;a[1].L = 1;
for(int i = 2; i <= n;i ++)
{
while( a[st[cnt]].x == a[i].x || (cnt >= 2 && check(a[st[cnt - 1]],a[st[cnt]],a[i])) )cnt --;
// if(vis[int(a[i].x)] )
// {
// for(int j = 1;j <= cnt;j ++)
// cout << st[j] << " ";
// puts("");
// }
a[i].L = st[cnt];
st[++ cnt] = i;
}
cnt = 0;st[++ cnt] = n;a[n].R = n;
for(int i = n - 1; i >= 1; i --)
{
while(a[st[cnt]].x == a[i].x || (cnt >= 2 && check(a[st[cnt - 1]],a[st[cnt]],a[i])) )cnt --;
a[i].R = st[cnt];
st[++ cnt] = i;
}
for(int i = 1;i <= n;i ++)
{
if(vis[int (a[i].x)])
{
Node l = a[a[i].L],r = a[a[i].R];
// cout << a[i].pos << " " << l.x << " " << l.y << " " << r.x << " " << r.y << endl;
ans[a[i].pos] = fun(l,r,a[i]);
}
}
for(int i = 1;i <= m; i ++)
printf("%.10f\n",ans[i] / acos(-1.0) * 180.0);
}
return 0;
}
/*
10
5
1 7 2 6 3 8 4 4 8 3
3
5 6 7
*/