【BZOJ】【2178】圆的面积并

时间:2021-09-28 17:12:58

自适应辛普森积分


  Orz Hzwer

  辛普森真是个强大的东西……很多东西都能积= =

  这题的正解看上去很鬼畜,至少我这种不会计算几何的渣渣是写不出来……(对圆的交点求图包,ans=凸包的面积+一堆弓形的面积,另外还有中空的情况……那种凸包怎么求啊喂!)

 /**************************************************************
Problem: 2178
User: Tunix
Language: C++
Result: Accepted
Time:8808 ms
Memory:1372 kb
****************************************************************/ //BZOJ 2178
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
using namespace std;
inline int getint(){
int v=,sign=; char ch=getchar();
while(ch<''||ch>''){ if (ch=='-') sign=-; ch=getchar();}
while(ch>=''&&ch<=''){ v=v*+ch-''; ch=getchar();}
return v*sign;
}
const int N=,INF=~0u>>;
const double eps=1e-;
typedef long long LL;
typedef double db;
/******************tamplate*********************/
int n,top,st,ed;
db xl[N],xr[N],ans;
bool del[N];
struct data{db x,y,r;}t[N],sk[N];
struct line{db l,r;}p[N];
db dis(data a,data b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool cmp1(data a,data b){return a.r<b.r;}
bool cmp2(data a,data b){return a.x-a.r<b.x-b.r;}
bool cmp3(line a,line b){return a.l<b.l;}
void init(){
scanf("%d",&n);
F(i,,n) scanf("%lf%lf%lf",&t[i].x,&t[i].y,&t[i].r);
sort(t+,t+n+,cmp1);
F(i,,n) F(j,i+,n)
if(dis(t[i],t[j])<=t[j].r-t[i].r){
del[i]=; break;
}
F(i,,n)if(!del[i]) sk[++top]=t[i];n=top;
sort(sk+,sk+n+,cmp2);
}
db getf(db x){
int j,sz=; db r,len=,dis;
F(i,st,ed){
if (x<=xl[i]||x>=xr[i])continue;
dis=sqrt(sk[i].r-(x-sk[i].x)*(x-sk[i].x));
p[++sz].l=sk[i].y-dis; p[sz].r=sk[i].y+dis;
}
sort(p+,p+sz+,cmp3);
F(i,,sz){
r=p[i].r;
for(j=i+;j<=sz;j++){
if(p[j].l>r)break;
if (r<p[j].r) r=p[j].r;
}
len+=r-p[i].l; i=j-;
}
return len;
}
db cal(db l,db fl,db fmid,db fr){
return (fl+fmid*+fr)*l/;
}
db simpson(db l,db mid,db r,db fl,db fmid,db fr,db s){
db m1=(l+mid)/,m2=(mid+r)/;
db f1=getf(m1),f2=getf(m2);
db g1=cal(mid-l,fl,f1,fmid),g2=cal(r-mid,fmid,f2,fr);
if (fabs(g1+g2-s)<eps)return g1+g2;
return simpson(l,m1,mid,fl,f1,fmid,g1)+
simpson(mid,m2,r,fmid,f2,fr,g2);
}
void work(){
int i,j;
db l,r,mid,fl,fr,fmid;
F(i,,n){
xl[i]=sk[i].x-sk[i].r;
xr[i]=sk[i].x+sk[i].r;
sk[i].r*=sk[i].r;
}
F(i,,n){
l=xl[i]; r=xr[i];
for(j=i+;j<=n;j++){
if (xl[j]>r) break;
if (xr[j]>r) r=xr[j];
}
st=i; ed=j-;i=j-;
mid=(l+r)/;
fl=getf(l); fr=getf(r); fmid=getf(mid);
ans+=simpson(l,mid,r,fl,fmid,fr,cal(r-l,fl,fmid,fr));
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("2178.in","r",stdin);
freopen("2178.out","w",stdout);
#endif
init();
work();
printf("%.3lf",ans);
return ;
}

2178: 圆的面积并

Time Limit: 20 Sec  Memory Limit: 259 MB
Submit: 908  Solved: 218
[Submit][Status][Discuss]

Description

给出N个圆,求其面积并

Input

先给一个数字N ,N< = 1000
接下来是N行是圆的圆心,半径,其绝对值均为小于1000的整数

Output

面积并,保留三位小数

Sample Input

721

。。。。。。

Sample Output

12707279.690

HINT

Source

[Submit][Status][Discuss]