HDU

题目

HDU - 5033 Building

做法

其实就是维护一个上凸壳

因为下凸时的右端点是不会起到贡献的作用

计算几何要注意的点(还是太弱了,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;
}/*
*/
原文地址:https://www.cnblogs.com/y2823774827y/p/10284382.html