\(\mathcal{Description}\)

  Link.

  求平面上 \(n\) 个圆的并的面积。

  \(n\le50\),可能被圆覆盖的横纵坐标区域在 \([-10^4,10^4]\)。

\(\mathcal{Solution}\)

  做了那么多计算几何之后写了这道不那么计算几何的计算几何题的题解。

  若想直接处理面积,就需要处理圆的各种相交关系,但是仅计算在某个 \(x_0\) 处,被圆的并覆盖的线段长度是很好处理地:每次 \(\mathcal O(n\log n)\) 排序后扫一遍即可。我们记 \(f(x)\) 表示 \(x_0=x\) 时,被圆的并覆盖的线段长度。所以问题转为求 \(\int_{-\infty}^{+\infty}f(x)dx\)。

  运用自适应 Simpson 积分,有 Simpson 公式:

\[\int_a^bf(x)\text dx\approx\frac{b-a}6\left(f(a)+4f(\frac{a+b}2)+f(b)\right)
\]

  其本质是用二次函数 \(g\) 近似地替换一个复杂的函数 \(f\),即设:

\[g(x)=Ax^2+Bx+C\approx f(x)\Longrightarrow\int_a^bf(x)\text dx\approx\int_b^ag(x)\text dx
\]

  利用 \(g(x)\) 化简积分,注意 \(g\) 仅是一种形式,我们的目的使用 \(f\) 的一些点值近似表示原积分。推导:

\[\begin{aligned}\int_a^bf(x)\text dx&\approx\int_a^b(Ax^2+Bx+C)\text dx\\&=\frac{A}3(b^3-a^3)+\frac{B}2(b^2-a^2)+C(b-a)\\&=\frac{2A(b^3-a^3)+3B(b^2-a^2)+6C(b-a)}6\\&=\frac{2A(b-a)(a^2+ab+b^2)+3B(b-a)(b+a)+6C(b-a)}6\\&=\frac{b-a}6\left(2Aa^2+2Aab+2Ab^2+3Bb+3Ba+6C\right)\\&=\frac{b-a}6\left[(Aa^2+Ba+C)+(Ab^2+Bb+C)+4\left(A(\frac{a+b}2)^2+B\cdot\frac{a+b}{2}+C\right)\right]\\&=\frac{b-a}6\left(g(a)+4g(\frac{a+b}2)+g(b)\right)\\&\approx\frac{b-a}6\left(f(a)+4f(\frac{a+b}2)+f(b)\right)\end{aligned}
\]

  记 \(h(a,b)=\frac{b-a}6\left(f(a)+4f(\frac{a+b}2)+f(b)\right)\),自适应 Simpson 积分的表达式如下:

\[\int_a^bf(x)\text dx\approx\begin{cases}h(a,b)&h(a,b)\approx^*h(a,\frac{a+b}2)+h(\frac{a+b}2,b)\\\int_a^{\frac{a+b}2}f(x)\text dx+\int_{\frac{a+b}2}^bf(x)\text dx&\text{otherwise}\end{cases}
\]

  其中 \(\approx^*\) 根据题目精度要求等自行判断。若精度不合适,则递归求解提升精确度。

  注意自适应 Simpson 积分只能处理平滑函数。例如依照上述算法,\(\int_0^{2\pi}|\sin x|\text dx=0\)(大雾)。

  回到本题,结合求 \(\mathcal O(n\log n)\) 求 \(f(x_0)\) 的方法近似求出 \(\int_{-\infty}^{+\infty}f(x)dx\) 即可。复杂度与圆的位置和要求精度有关(aka. 我不知道 qwq)。

\(\mathcal {Code}\)

  讲道理若某两块并在 \(x\) 轴上的投影相离应该分开求积分,但那样写我 WA 掉了 qwq。

/* Clearink */

#include <cmath>
#include <cstdio>
#include <vector>
#include <algorithm> typedef std::pair<double, double> PDD; const int MAXN = 50;
const double EPS = 1e-9;
int n;
bool ban[MAXN + 5]; inline double sqr ( const double a ) { return a * a; }
inline double dabs ( const double a ) { return a < 0 ? -a : a; }
inline double dmin ( const double a, const double b ) { return a < b ? a : b; }
inline double dmax ( const double a, const double b ) { return a < b ? b : a; } struct Circle { double x, y, r; } O[MAXN + 5]; inline double func ( const double x ) {
static std::vector<PDD> sec; sec.clear ();
for ( int i = 1; i <= n; ++i ) {
const Circle& C ( O[i] );
if ( dabs ( x - C.x ) < C.r ) {
double yd = sqrt ( sqr ( C.r ) - sqr ( dabs ( C.x - x ) ) );
sec.push_back ( { C.y - yd, C.y + yd } );
}
}
std::sort ( sec.begin (), sec.end () );
double las = -1e9, ret = 0;
for ( PDD s: sec ) {
las = dmax ( las, s.first );
ret += dmax ( 0, s.second - las );
las = dmax ( las, s.second );
}
return ret;
} inline double scalc ( const double lx, const double rx,
const double fl, const double fm, const double fr ) {
return ( fl + 4 * fm + fr ) / 6 * ( rx - lx );
} inline double simpson ( const double lx, const double rx,
const double fl, const double fm, const double fr ) {
double mx = 0.5 * ( lx + rx );
double fll = func ( 0.5 * ( lx + mx ) ), frr = func ( 0.5 * ( mx + rx ) );
double s = scalc ( lx, rx, fl, fm, fr );
double sl = scalc ( lx, mx, fl, fll, fm ), sr = scalc ( mx, rx, fm, frr, fr );
if ( dabs ( s - sl - sr ) < EPS ) return sl + sr;
return simpson ( lx, mx, fl, fll, fm ) + simpson ( mx, rx, fm, frr, fr );
} int main () {
scanf ( "%d", &n );
double mn = 1e9, mx = -1e9;
for ( int i = 1; i <= n; ++i ) {
scanf ( "%lf %lf %lf", &O[i].x, &O[i].y, &O[i].r );
mn = dmin ( mn, O[i].x - O[i].r );
mx = dmax ( mx, O[i].x + O[i].r );
}
printf ( "%.5f\n", simpson ( mn, mx,
func ( mn ), func ( 0.5 * ( mn + mx ) ), func ( mx ) ) );
return 0;
}

Solution -「SPOJ-VCIRCLES」Area of Circles的更多相关文章

  1. 「SPOJ 3105」Power Modulo Inverted

    「SPOJ 3105」Power Modulo Inverted 传送门 题目大意: 求关于 \(x\) 的方程 \[a^x \equiv b \;(\mathrm{mod}\; p) \] 的最小自 ...

  2. Solution -「ARC 104E」Random LIS

    \(\mathcal{Description}\)   Link.   给定整数序列 \(\{a_n\}\),对于整数序列 \(\{b_n\}\),\(b_i\) 在 \([1,a_i]\) 中等概率 ...

  3. Solution -「CTS 2019」「洛谷 P5404」氪金手游

    \(\mathcal{Description}\)   Link.   有 \(n\) 张卡牌,第 \(i\) 张的权值 \(w_i\in\{1,2,3\}\),且取值为 \(k\) 的概率正比于 \ ...

  4. Solution -「BZOJ 3812」主旋律

    \(\mathcal{Description}\)   Link.   给定含 \(n\) 个点 \(m\) 条边的简单有向图 \(G=(V,E)\),求 \(H=(V,E'\subseteq E)\ ...

  5. Solution -「CF 1342E」Placing Rooks

    \(\mathcal{Description}\)   Link.   在一个 \(n\times n\) 的国际象棋棋盘上摆 \(n\) 个车,求满足: 所有格子都可以被攻击到. 恰好存在 \(k\ ...

  6. Solution -「简单 DP」zxy 讲课记实

    魔法题位面级乱杀. 「JOISC 2020 Day4」治疗计划 因为是不太聪明的 Joker,我就从头开始理思路了.中途也会说一些和 DP 算法本身有关的杂谈,给自己的冗长题解找借口. 首先,治疗方案 ...

  7. Solution -「基环树」做题记录

    写的大多只是思路,比较简单的细节和证明过程就不放了,有需者自取. 基环树简介 简单说一说基环树吧.由名字扩展可得这是一类以环为基础的树(当然显然它不是树. 通常的表现形式是一棵树再加一条非树边,把图画 ...

  8. Solution -「WC 2022」秃子酋长

    \(\mathscr{Description}\)   Link. (It's empty temporarily.)   给定排列 \(\{a_n\}\),\(q\) 次询问,每次给出 \([l,r ...

  9. Solution -「JSOI 2019」「洛谷 P5334」节日庆典

    \(\mathscr{Description}\)   Link.   给定字符串 \(S\),求 \(S\) 的每个前缀的最小表示法起始下标(若有多个,取最小的).   \(|S|\le3\time ...

随机推荐

  1. jsp使用${}语法,对应的spring后台使用Model

    实现的前提,一定要在jsp文件顶部加上 <%@page isELIgnored="false" %> 如上图${aa}与${bb},是直接使用Model的key值对应的 ...

  2. SCryptPasswordEncoder 单向加密 --- 心得

    1.前言 * BCryptPasswordEncoder相关知识:* 用户表的密码通常使用MD5等不可逆算法加密后存储,为防止彩虹表破解更会先使用一个特定的字符串(如域名)加密,然后再使用一个随机的s ...

  3. 自定义Nginx日志格式获取IP地址的省市份信息

    注:图片如果损坏,点击文章链接:https://www.toutiao.com/i6806672112477012493/ 在linux中nginx日志产生的格式是下面的配置: $remote_add ...

  4. C# 反射调用拓展类方法

    今天封装Protobuf封包时候遇到一个问题: Protobuf的反序列化方法MergeFrom,是写在扩展类里的:c#拓展类 通过反射获取不到这个方法,就没法使用Type来泛型封装... 然而仔细一 ...

  5. Go 变量及基本数据类型1

    #### Go 变量及基本数据类型(一)今天主要学习一下Go 中的变量及基本数据类型: 如何申明,使用变量,以及基本数据类型的介绍和使用细节; ##### 变量的介绍1. 变量相当于内存中一个数据存储 ...

  6. 项目管理软件jira安装

    JIRA是Atlassian公司出品的项目与事务跟踪工具,被广泛应用于缺陷跟踪.客户服务.需求收集.流程审批.任务跟踪.项目跟踪和敏捷管理等工作领域. 官方文档https://confluence.a ...

  7. linux 创建用户 用户组,sudo,禁止root远程ssh登录

    创建用户  useradd hanli 为新用户设置密码(在root下可以为普通用户重置密码)  passwd hanli 创建用户组  groupadd  op 将用户添加到用户组  usermod ...

  8. LNMP架构搭建

    目录 一:LNMP架构简介 1.Nginx与uwsgi 二:django框架+python 1.创建用户 2.安装依赖包 3.安装uwsgi和django 4.测试python 5.创建django项 ...

  9. 学习Java第3天

    今天所做的工作: 1.循环结构 2.字符串 3.数组 4.面向对象概述 明天工作安排: 1.类和对象 2.包装类 所遇到的问题及解决方法: 1.循环foreach语句 2.字符串初始化与c++的差异 ...

  10. Redis性能分析思路

    Redis性能分析有几个大的方向.分别是 (1)基准对比 (2)配置优化 (3)数据持久化 (4)键值优化 (5)缓存淘汰 (6)Redis集群 基准对比 在没有业务实例运行的情况下,在服务器上通过测 ...