bzoj 2178 圆的面积并 —— 辛普森积分
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2178
先看到这篇博客:https://www.cnblogs.com/heisenberg-/p/6740654.html
好像本应算弓形面积、三角形面积之类的,但不会...于是用辛普森积分硬做...
参考了这篇博客:https://blog.csdn.net/orpinex/article/details/7311363
然而如果写成精度友好型的 asr ( *15, /15, eps/2 ),或T或RE的,不精度友好反而好了...
为什么一开始传的范围是所有圆边界的 min, max 就会WA,传 -inf, inf 就A了...
总之写的时候还是尽量稳妥一点吧...
代码如下:
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- #include<cmath>
- using namespace std;
- typedef double db;
- int const xn=,inf=;
- db const eps=1e-;
- int n;
- bool tmp[xn];
- struct N{int x,y,r;}c[xn];
- struct S{db l,r;}seg[xn];
- int rd()
- {
- int ret=,f=; char ch=getchar();
- while(ch<''||ch>''){if(ch=='-')f=; ch=getchar();}
- while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
- return f?ret:-ret;
- }
- int dmp(db x)
- {
- if(fabs(x)<eps)return ;
- else if(x>eps)return ;
- else return -;
- }
- db sqr(db x){return x*x;}
- bool cmp(S a,S b){return dmp(a.l-b.l)<||(dmp(a.l-b.l)==&&dmp(a.r-b.r)<);}
- bool cmp2(N a,N b){return a.r<b.r;}
- db maxx(db x,db y){if(dmp(x-y)<)return y; return x;}
- bool in(int a,int b){return sqr(c[a].x-c[b].x)+sqr(c[a].y-c[b].y)<=sqr(c[a].r-c[b].r);}
- void init()
- {
- sort(c+,c+n+,cmp2);
- for(int i=;i<=n;i++)
- {
- for(int j=i+;j<=n;j++)
- if(in(i,j)){tmp[i]=; break;}
- }
- int tot=;
- for(int i=;i<=n;i++)if(!tmp[i])c[++tot]=c[i];
- n=tot;
- }
- db f(db x)
- {
- int cnt=;
- for(int i=;i<=n;i++)
- {
- if(dmp(fabs(c[i].x-x)-c[i].r)>)continue;
- db dis=sqrt(sqr(c[i].r)-sqr(x-c[i].x));
- seg[++cnt].l=c[i].y-dis; seg[cnt].r=c[i].y+dis;
- }
- sort(seg+,seg+cnt+,cmp);
- db ret=,r=-inf;
- for(int i=;i<=cnt;i++)
- {
- if(dmp(seg[i].l-r)>)ret+=seg[i].r-seg[i].l,r=seg[i].r;
- else if(dmp(seg[i].r-r)>)ret+=seg[i].r-r,r=seg[i].r;
- }
- return ret;
- }
- db simp(db l,db r){return (r-l)/*(f(l)+*f((l+r)/)+f(r));}
- db asr(db l,db r,db eps,db lst)
- {
- db mid=(l+r)/;
- db ls=simp(l,mid),rs=simp(mid,r);
- if(fabs(ls+rs-lst)<=*eps)return ls+rs+(ls+rs-lst)/;
- return asr(l,mid,eps/,ls)+asr(mid,r,eps/,rs);
- }
- db asr(db l,db r,db lst)
- {
- db mid=(l+r)/;
- db ls=simp(l,mid),rs=simp(mid,r);
- if(fabs(ls+rs-lst)<=eps)return ls+rs;
- return asr(l,mid,ls)+asr(mid,r,rs);
- }
- int main()
- {
- n=rd(); int L=inf,R=-inf;
- for(int i=;i<=n;i++)
- c[i].x=rd(),c[i].y=rd(),c[i].r=rd(),
- L=min(L,c[i].x-c[i].r),R=max(R,c[i].x+c[i].r);
- init();
- //printf("%.3f\n",asr(L,R,eps,simp(L,R)));
- //printf("%.3f\n",asr(L,R,simp(L,R)));
- printf("%.3f\n",asr(-inf,inf,simp(-inf,inf)));
- //printf("%.3f\n",asr(-inf,inf,eps,simp(-inf,inf)));
- return ;
- }
然而这样其实会错HAHA,随便来个数据竟然就错了:
3
0 0 1
0 0 1
100 100 1
应该输出 6.283,但上面的代码以及许多题解输出都是 3.142 ...
于是换了一种写法,对每个连续段做积分,这样避免了空白区域对积分结果的影响;
而且发现求一次 f(x) 很慢,所以之前求过的尽量重复利用;
然后就T了,调了两小时...
TLE 的原因竟然是 sort 里面传了 cmp() 函数??!!!如果改成重载结构体小于号,就不T了呵呵-_-
所以还是要注意代码习惯阿。
代码如下:
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- #include<cmath>
- using namespace std;
- typedef double db;
- int const xn=,inf=;
- db const eps=1e-;
- int n,st,ed,xl[xn],xr[xn];
- bool tmp[xn];
- struct N{
- int x,y,r;
- bool operator < (const N &b) const
- {return r<b.r;}
- }c[xn];
- struct S{
- db l,r;
- bool operator < (const S &b) const
- {return l<b.l;}
- }seg[xn];
- int rd()
- {
- int ret=,f=; char ch=getchar();
- while(ch<''||ch>''){if(ch=='-')f=; ch=getchar();}
- while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
- return f?ret:-ret;
- }
- db sqr(db x){return x*x;}
- //bool cmp(S a,S b){return a.l<b.l;}
- //bool cmp2(N a,N b){return a.r<b.r;}
- bool cmp3(N a,N b){return a.x-a.r<b.x-b.r;}
- bool in(int a,int b){return sqr(c[a].x-c[b].x)+sqr(c[a].y-c[b].y)<=sqr(c[a].r-c[b].r);}
- void init()
- {
- sort(c+,c+n+);//cmp2
- for(int i=;i<=n;i++)
- {
- for(int j=i+;j<=n;j++)
- if(in(i,j)){tmp[i]=; break;}
- }
- int tot=;
- for(int i=;i<=n;i++)if(!tmp[i])c[++tot]=c[i];
- n=tot;
- sort(c+,c+n+,cmp3);//
- }
- db f(db x)
- {
- int cnt=;
- for(int i=st;i<=ed;i++)
- {
- if(xl[i]>=x||xr[i]<=x)continue;
- db dis=sqrt(c[i].r-sqr(x-c[i].x));//(sqr)
- seg[++cnt].l=c[i].y-dis; seg[cnt].r=c[i].y+dis;
- }
- sort(seg+,seg+cnt+);//cmp
- db ret=,r=-inf;
- for(int i=,j;i<=cnt;i=j)
- {
- r=seg[i].r;
- for(j=i+;j<=cnt&&seg[j].l<=r;j++)
- if(r<seg[j].r)r=seg[j].r;
- ret+=r-seg[i].l;
- }
- return ret;
- }
- db simp(db len,db fl,db fr,db fm){return len/*(fl+*fm+fr);}
- db asr(db l,db r,db mid,db fl,db fr,db fm,db lst)
- {
- db lmid=(l+mid)/,flm=f(lmid),rmid=(mid+r)/,frm=f(rmid);
- db ls=simp(mid-l,fl,fm,flm),rs=simp(r-mid,fm,fr,frm);
- if(fabs(ls+rs-lst)<=eps)return ls+rs;
- return asr(l,mid,lmid,fl,fm,flm,ls)+asr(mid,r,rmid,fm,fr,frm,rs);
- }
- int main()
- {
- n=rd();
- for(int i=;i<=n;i++)
- c[i].x=rd(),c[i].y=rd(),c[i].r=rd();
- init(); db ans=;
- for(int i=;i<=n;i++)
- xl[i]=c[i].x-c[i].r,xr[i]=c[i].x+c[i].r,c[i].r=c[i].r*c[i].r;
- for(int i=,j;i<=n;i=j)
- {
- int l=xl[i],r=xr[i];
- for(j=i+;xl[j]<=r&&j<=n;j++)if(xr[j]>r)r=xr[j];
- st=i; ed=j-; db mid=(l+r)/;
- db fl=f(l),fm=f(mid),fr=f(r);
- ans+=asr(l,r,mid,fl,fr,fm,simp(r-l,fl,fr,fm));
- }
- printf("%.3f\n",ans);
- return ;
- }
bzoj 2178 圆的面积并 —— 辛普森积分的更多相关文章
- BZOJ 2178: 圆的面积并 [辛普森积分 区间并]
2178: 圆的面积并 Time Limit: 20 Sec Memory Limit: 259 MBSubmit: 1740 Solved: 450[Submit][Status][Discus ...
- bzoj 2178 圆的面积并——辛普森积分
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2178 把包含的圆去掉.横坐标不相交的一段一段圆分开算.算辛普森的时候预处理 f( ) ,比如 ...
- BZOJ 2178: 圆的面积并 (辛普森积分)
code #include <set> #include <cmath> #include <cstdio> #include <cstring> #i ...
- BZOJ 2178 圆的面积并 ——Simpson积分
[题目分析] 史上最良心样例,史上最难调样例. Simpson积分硬上. 听说用long double 精度1e-10才能过. 但是double+1e-6居然过了. [代码] #include < ...
- [BZOJ 2178] 圆的面积并 【Simpson积分】
题目链接:BZOJ - 2178 题目分析 用Simpson积分,将圆按照 x 坐标分成连续的一些段,分别用 Simpson 求. 注意:1)Eps要设成 1e-13 2)要去掉被其他圆包含的圆. ...
- BZOJ 1845: [Cqoi2005] 三角形面积并 (辛普森积分)
大力辛普森积分 精度什么的搞了我好久- 学到了Simpson的一个trick 深度开11,eps开1e-4.跑的比有些扫描线还快- CODE #include <bits/stdc++.h> ...
- bzoj 2178 圆的面积并【simpson积分】
直接套simpson,f可以直接把圆排序后扫一遍所有圆,这样维护一个区间就可以避免空段. 然而一定要去掉被其他圆完全覆盖的圆,否则会TLE #include<iostream> #incl ...
- 【BZOJ】2178: 圆的面积并
http://www.lydsy.com/JudgeOnline/problem.php?id=2178 题意:给出n<=1000个圆,求这些圆的面积并 #include <cstdio& ...
- BZOJ 1502: [NOI2005]月下柠檬树 [辛普森积分 解析几何 圆]
1502: [NOI2005]月下柠檬树 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1070 Solved: 596[Submit][Status] ...
随机推荐
- bash批量去前缀
#!/bin/sh for aFile in *; do oldfile=`basename "$aFile"` newfile=${oldfile::} echo ${oldfi ...
- 我的Android进阶之旅------>Android 标签的用法
布局资源文件的根节点可以使用容器控件(如LinearLayout.FrameLayout等),也可以使用非容器控件(如:EditText.TextView等).对于非容器控件,只能在非容器控件标签中放 ...
- linux c编程:线程互斥二 线程死锁
死锁就是不同的程序在运行时因为某种原因发生了阻塞,进而导致程序不能正常运行.阻塞程序的原因通常都是由于程序没有正确使用临界资源. 我们举个日常生活中的例子来比喻死锁.我们把马路上行驶的汽车比作运行着的 ...
- sublime 快捷键,左菜单乱码
sublime 快捷键安装 packagecontrol https://packagecontrol.io/installation#st3 import urllib.request,os,has ...
- CentOS7安装MySQL8.0小计
之前讲配置文件和权限的时候有很多MySQL8的知识,有同志说安装不太一样,希望发个文,我这边简单演示一下 1.环境安装 下载MySQL提供的CentOS7的yum源 官方文档:<https:// ...
- activiti--6-------------------------------------连线(一般数据库表的查询顺序)
一.流程图 二.这次把流程图和Java类放在一个包下 三.代码 package com.xingshang.f_sequenceFlow; import java.io.InputStream; im ...
- R中常用数据挖掘算法包
数据挖掘主要分为4类,即预测.分类.聚类和关联,根据不同的挖掘目的选择相应的算法.下面对R语言中常用的数据挖掘包做一个汇总: 连续因变量的预测: stats包 lm函数,实现多元线性回归 stats包 ...
- C# unicode GBK UTF-8和汉字互转
界面: 源码: using System; using System.Collections.Generic; using System.ComponentModel; using System.Da ...
- GUI菜单——菜单条、菜单、子条目之间关系
菜单:注意区分三个概念:菜单条.菜单.菜单项 将菜单条添加到窗体,菜单条下面包括菜单,菜单下面可以使菜单或者菜单项 菜单项是最后一个.菜单后面有三角标示. 菜单条[文件] 子菜单--子条目 子条目 示 ...
- 【leetcode】Balanced Binary Tree
Given a binary tree, determine if it is height-balanced. For this problem, a height-balanced binary ...