BZOJ2178 圆的面积并(simpson积分)
板子题。可以转一下坐标防止被卡。精度和常数实在难以平衡。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; #define ll long long #define double long double #define N 1010 char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int 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<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n; const double PI=acos(-1.0); double x[N],y[N],r[N]; struct data { double x;int op; bool operator <(const data&a) const { return x<a.x; } }a[N<<1]; const double eps=1E-7; double f(double k) { int m=0; for (int i=1;i<=n;i++) if (fabs(x[i]-k)<r[i]) { double t=sqrt(r[i]*r[i]-(x[i]-k)*(x[i]-k)); a[++m].x=y[i]-t,a[m].op=1; a[++m].x=y[i]+t,a[m].op=-1; } sort(a+1,a+m+1); double ans=0,cur;int u=0; for (int i=1;i<=m;i++) { if (u==0) cur=a[i].x; u+=a[i].op; if (u==0) ans+=a[i].x-cur; } return ans; } double simpson(double l,double r) { return (r-l)*(f(l)+f(r)+4*f((l+r)/2))/6; } double calc(double l,double r,double simp) { double mid=(l+r)/2,x=simpson(l,mid),y=simpson(mid,r); if (fabs(x+y-simp)<eps) return x+y; else return calc(l,mid,x)+calc(mid,r,y); } int main() { #ifndef ONLINE_JUDGE freopen("bzoj2178.in","r",stdin); freopen("bzoj2178.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif n=read();double L=2000,R=-2000; for (int i=1;i<=n;i++) { x[i]=read(),y[i]=read(),r[i]=read(); double u=x[i]*sin(PI/3)+y[i]*cos(PI/3),v=x[i]*cos(PI/3)-y[i]*sin(PI/3); x[i]=u,y[i]=v; L=min(L,x[i]-r[i]),R=max(R,x[i]+r[i]); } #undef double printf("%.3f",(double)calc(L,R,simpson(L,R))); return 0; }