题目
做法
其实就是维护一个上凸壳
因为下凸时的右端点是不会起到贡献的作用
计算几何要注意的点(还是太弱了,dalao请略过):
(atan()):通过比值计算弧度
(1rad=frac{180^{o}}{pi})
My complete code
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<vector>
#include<ctime>
#include<stack>
#include<cmath>
using namespace std;
typedef long long LL;
const LL maxn=300000;
const double inf=10000000.0;
const double Pi=acos(-1.0);
inline LL Read(){
LL x(0),f(1); char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')f=-1;c=getchar();
}
while(c>='0'&&c<='9')
x=(x<<3)+(x<<1)+c-'0',c=getchar();
return x*f;
}
LL n,m,T,cas;
double ans[maxn];
struct node{
double x,y;
LL id;
node(){};
node(double xx,double yy,LL idd):x(xx),y(yy),id(idd){};
bool operator <(const node &b)const{
return x<b.x;
}
node operator -(const node &b)const{
return node(x-b.x,y-b.y,0);
}
}q[maxn];
node sta[maxn];
inline bool compare(node a,node b){
return a.y*b.x-b.y*a.x>0;
}
inline bool Check(node a,node b,node c){
return compare(a-c,c-b);
}
inline double Calc(node a,node b){
return atan((b.x-a.x)/a.y);
}
inline void Solve(){
LL top=0;
for(LL i=1;i<=n;++i){
if(q[i].id){
while(top>=2&&Check(sta[top-1],sta[top],q[i]))
--top;
ans[q[i].id]+=Calc(sta[top],q[i]);
}else{
while(top&&sta[top].y<=q[i].y)
--top;
while(top>=2&&Check(sta[top-1],sta[top],q[i]))
--top;
sta[++top]=q[i];
}
}
}
int main(){
T=Read();
while(T--){
n=Read();
for(LL i=1;i<=n;++i){
scanf("%lf%lf",&q[i].x,&q[i].y);
q[i].id=0;
}
m=Read();
for(LL i=1;i<=m;++i){
scanf("%lf",&q[++n].x),
q[n].y=0;
q[n].id=i;
}
sort(q+1,q+1+n),
memset(ans,0,sizeof(ans));
Solve();
reverse(q+1,q+1+n);
for(LL i=1;i<=n;++i)
q[i].x=inf-q[i].x;
Solve();
printf("Case #%lld:
",++cas);
for(LL i=1;i<=m;++i)
printf("%.10lf
",ans[i]*180/Pi);
}
return 0;
}/*
*/