题意:
给定一棵由若干个圆台和圆锥组成的树,求这棵树在与地面成$alpha$角的平行光束照射下产生的投影的面积。
$nleq 500$。
题解:
显然投影下去之后每个圆的$r$不变,而高度$h$变成$frac{h}{ an{alpha}}$。
圆的面积可以直接算,两个圆的公切线形成的梯形用三角函数推一下也可以直接算。
那么直接$Simpson$积分算一下就行了。注意区间$l,r$应该对所有圆算一遍$min,max$来取值,因为会出现圆套圆的情况。
复杂度$O(n^{2}log{n})$(大概吧)。
套路:
- 求一个整体复杂但可以求得单点极值的图形面积$ ightarrow$Simpson积分。
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define maxn 200005 #define maxm 500005 #define inf 0x7fffffff #define eps 1e-6 #define ll long long #define rint register int #define debug(x) cerr<<#x<<": "<<x<<endl #define fgx cerr<<"--------------"<<endl #define dgx cerr<<"=============="<<endl using namespace std; int n; double H[maxn],R[maxn],C[maxn]; inline int read(){ int x=0,f=1; char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } inline double f(double x){ double res=0; for(rint i=1;i<=n;i++) if(C[i]-x<R[i] && C[i]-x>-R[i]) res=max(res,sqrt(R[i]*R[i]-(C[i]-x)*(C[i]-x))); for(rint i=1;i<n;i++){ double x1=C[i]+R[i]*(R[i]-R[i+1])/H[i]; double x2=C[i+1]+R[i+1]*(R[i]-R[i+1])/H[i]; if(x1<x && x2>x){ double y1=sqrt(R[i]*R[i]-(C[i]-x1)*(C[i]-x1)); double y2=sqrt(R[i+1]*R[i+1]-(C[i+1]-x2)*(C[i+1]-x2)); res=max(res,y1+(x-x1)*(y2-y1)/(x2-x1)); } } return res; } inline double simpson(double l,double r){return (r-l)*(f(l)+f(r)+4.0*f((l+r)/2.0))/6.0;} inline double solve(double l,double r){ double mid=(l+r)/2.0,S=simpson(l,r),S1=simpson(l,mid),S2=simpson(mid,r); return (abs(S1+S2-S)<eps)?(S1+S2):(solve(l,mid)+solve(mid,r)); } int main(){ n=read(); double theta; scanf("%lf",&theta); double tp=tan(theta); for(rint i=0;i<=n;i++) scanf("%lf",&H[i]),H[i]/=tp; for(rint i=1;i<=n;i++) scanf("%lf",&R[i]); R[++n]=eps,C[1]=R[1]; for(rint i=2;i<=n;i++) C[i]=C[i-1]+H[i-1]; double l=0,r=0; for(rint i=1;i<=n;i++) r=max(r,C[i]+R[i]),l=min(l,C[i]-R[i]); printf("%.2lf ",solve(l,r)*2.0); return 0; }