洛谷 P3268 [JLOI2016]圆的异或并
洛谷 P3268 [JLOI2016]圆的异或并
题目描述
在平面上有两两不相交的\(n\)个圆,即其关系只有相离和包含。求这些圆的异或面积并。
异或面积并为:当一片区域被奇数个圆包含则计算其面积,否则不计算。
输出所有圆的异或面积并除以\(\pi\)的结果。
\(n\le 200000\)。
Solution
前置知识:扫描线,set。
可以发现,由于圆是不相交的,那么这种包含关系可以看作是一棵森林(许多有根树构成的图)。
比如像这个几个圆

可以变成

设每个根的深度为1,那么深度为奇数的节点的面积是需要加上的,深度为偶数的节点的面积是需要减去的。
即
\]
同扫描线的思想,我们模拟出有一条垂直于\(x\)轴的直线从左向右移动。
- 当其与某个圆开始触碰到的时候,就将这个圆拆分为上半圆和下半圆插入set中。这个set是按照圆的高度排序的。由于保证了圆和圆之间不相交,所以可以直接计算扫描线与半圆的交点作为关键字排序。圆和圆之间不相交保证了这个关键字的相对大小一定不会变。
查询刚刚插入的圆的上半圆的前驱(在set中的所有半圆中,在当前圆下方最近的半圆)。如果它的前驱是一个上半圆,那么当前圆的深度等于其前驱的深度;若前驱是一个下半圆,那么说明当前圆被其前驱所包含,深度为前驱的深度+1。
- 遇到圆的右边界就直接将其两个半圆从set中删除即可。
因为set中要插入同一id的两个半圆,那么只要用up表示当前圆是上半圆还是下半圆即可。重载运算符时,可以比较当前扫描线与半圆的交点,也可以以圆心的纵坐标为第一关键字,以上/下半圆为第二关键字进行比较。
注意,如果是以扫描线与半圆的交点进行比较的话,在扫描线进入/离开一个圆的时候,扫描线与两个半圆的交点会重合。需要在比较函数中将上半圆的交点纵坐标加上一个\(eps\)即可。
Code
我的排序方法是比较当前半圆和扫描线的交点。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#include<limits.h>
#define IL inline
#define re register
#define LL long long
#define ULL unsigned long long
#ifdef TH
#define debug printf("Now is %d\n",__LINE__);
#else
#define debug
#endif
using namespace std;
template<class T>inline void read(T&x)
{
char ch=getchar();
int fu;
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=-1,ch=getchar();
x=ch-'0';ch=getchar();
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
x*=fu;
}
inline LL read()
{
LL x=0,fu=1;
char ch=getchar();
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=-1,ch=getchar();
x=ch-'0';ch=getchar();
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return x*fu;
}
int G[55];
template<class T>inline void write(T x)
{
int g=0;
if(x<0) x=-x,putchar('-');
do{G[++g]=x%10;x/=10;}while(x);
for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n');
}
#define N 200010
int n,nowx;
LL X[N],Y[N],R[N];
struct Opt
{
LL pos;
int x;
bool insert;
Opt(LL a=0,int b=0,bool c=0)
{
pos=a,x=b,insert=c;
}
IL bool operator<(const Opt& z)const
{
return pos<z.pos;
}
};
vector<Opt>opt;
bool dep[N];
#define eps 1e-6
struct O
{
int x;
bool up;
O(int xx=0,bool u=1)
{
x=xx,up=u;
}
double calc()const
{
if(up) return Y[x]+sqrt(R[x]*R[x]-(X[x]-nowx)*(X[x]-nowx))+eps;
return Y[x]-sqrt(R[x]*R[x]-(X[x]-nowx)*(X[x]-nowx));
}
IL bool operator<(const O& z)const
{
return calc()<z.calc();
}
};
set<O>s;
set<O>::iterator it;
int main()
{
n=read();
for(int i=1;i<=n;i++)
{
X[i]=read();
Y[i]=read();
R[i]=read();
opt.push_back(Opt(X[i]-R[i],i,1));
opt.push_back(Opt(X[i]+R[i],i,0));
}
sort(opt.begin(),opt.end());
LL ans=0;
for(int i=0;i<opt.size();i++)
{
nowx=opt[i].pos;
if(opt[i].insert)
{
it=s.insert(O(opt[i].x,1)).first;
if(it==s.begin())
{
dep[opt[i].x]=1;
}
else
{
it--;
if(it->up)
{
dep[opt[i].x]=dep[it->x];
}
else
{
dep[opt[i].x]=dep[it->x]^1;
}
}
s.insert(O(opt[i].x,0));
if(dep[opt[i].x]) ans+=R[opt[i].x]*R[opt[i].x];
else ans-=R[opt[i].x]*R[opt[i].x];
}
else
{
s.erase(O(opt[i].x,1));
s.erase(O(opt[i].x,0));
}
}
write(ans);
return 0;
}
总结
扫描线是一种重要的思想。在其应用的过程中常常需要用到set,线段树等数据结构进行维护。
洛谷 P3268 [JLOI2016]圆的异或并的更多相关文章
- 洛谷P3268 [JLOI2016]圆的异或并(扫描线)
扫描线还不是很熟啊--不管是从想的方面还是代码实现的方面-- 关于这题,考虑一条平行于\(y\)轴的扫描线从左到右扫描每一个圆,因为只有相离和内含两种关系,只用在切线处扫描即可 我们设上半圆为1,下半 ...
- bzoj4561: [JLoi2016]圆的异或并 圆的扫描线
地址:http://www.lydsy.com/JudgeOnline/problem.php?id=4561 题目: 4561: [JLoi2016]圆的异或并 Time Limit: 30 Sec ...
- BZOJ4561 JLoi2016 圆的异或并 【扫描线】【set】*
BZOJ4561 JLoi2016 圆的异或并 Description 在平面直角坐标系中给定N个圆.已知这些圆两两没有交点,即两圆的关系只存在相离和包含.求这些圆的异或面积并.异或面积并为:当一片区 ...
- 【BZOJ4561】[JLoi2016]圆的异或并 扫描线
[BZOJ4561][JLoi2016]圆的异或并 Description 在平面直角坐标系中给定N个圆.已知这些圆两两没有交点,即两圆的关系只存在相离和包含.求这些圆的异或面积并.异或面积并为:当一 ...
- 洛谷 P4592: bzoj 5338: [TJOI2018]异或
题目传送门:洛谷P4592. 题意简述: 题面说的很清楚了. 题解: 发现没有修改很快乐.再看异或最大值操作,很容易想到可持久化 01trie. 这里要把 01trie 搬到树上,有点难受. 树剖太捞 ...
- bzoj4561: [JLoi2016]圆的异或并
Description 在平面直角坐标系中给定N个圆.已知这些圆两两没有交点,即两圆的关系只存在相离和包含.求这些圆的异或面 积并.异或面积并为:当一片区域在奇数个圆内则计算其面积,当一片区域在偶数个 ...
- bzoj 4561: [JLoi2016]圆的异或并
Description 在平面直角坐标系中给定N个圆.已知这些圆两两没有交点,即两圆的关系只存在相离和包含.求这些圆的异或面 积并.异或面积并为:当一片区域在奇数个圆内则计算其面积,当一片区域在偶数个 ...
- BZOJ 4561 [JLoi2016]圆的异或并 ——扫描线
扫描线的应用. 扫描线就是用数据结构维护一个相对的顺序不变,带修改的东西. 通常只用于一次询问的情况. 抽象的看做一条垂直于x轴直线从左向右扫过去. 这道题目要求求出所有圆的异或并. 所以我们可以求出 ...
- [JLOI2016]圆的异或并
Description 在平面直角坐标系中给定N个圆.已知这些圆两两没有交点,即两圆的关系只存在相离和包含.求这些圆的异或面积并.异或面积并为:当一片区域在奇数个圆内则计算其面积,当一片区域在偶数个圆 ...
- 洛谷 P3267 - [JLOI2016/SHOI2016]侦察守卫(树形 dp)
洛谷题面传送门 经典题一道,下次就称这种"覆盖距离不超过 xxx 的树形 dp"为<侦察守卫模型> 我们考虑树形 \(dp\),设 \(f_{x,j}\) 表示钦定了 ...
随机推荐
- Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
在众多开源项目中,高颜值.功能强大且部署简单的项目往往更能俘获开发者的心.然而,实际部署 Web 应用时,面对数据库.缓存.消息队列等复杂的依赖关系,常常令人头疼.Docker 的开源为我们普及了容器 ...
- 1、从DeepSeek API调用到Semantic Kernel集成:深度解析聊天机器人开发全链路
引言:AI时代下的聊天机器人开发范式演进 在生成式AI技术爆发的当下,基于大语言模型(LLM)的聊天机器人开发已形成标准化技术链路.本文将结合DeepSeek API与微软Semantic Kerne ...
- HTTP 和 RPC
TCP 是传输层的协议,而基于 TCP 造出来的 HTTP 和各类 RPC 协议,它们都只是定义了不同消息格式的应用层协议而已. RPC(Remote Procedure Call),又叫做远程过程调 ...
- CentOS7图形化界面和命令行界面之间的转换
最近在学习Lunix操作系统下的CentOS7系统,参考了网页上大多数的资料并进行在自己的亲身实践,最终想要记录一下我在CentOS7系统中有关命令行和图形化界面之间的转换.1.查看当前的默认界面形式 ...
- “决策-寻找过程”的黄金秘密工具,1/e 法则之应用(尤其日常生活中的应用)
https://www.ccgxk.com/magicword/327.html 目录 引言 著名的 1/e 法则内容和解释 应用到生活中的 1/e 法则是什么样? 相亲案例 看书.看电影案例 生活质 ...
- 在IIS Express下部署NuGet私服
用途 个人开发,部署自己的NuGet pkg. 环境 Win11 IIS Express (轻度使用,不安装IIS,而使用VS预装的IIS Express) VS2022 步骤 开发环境准备 因我拟用 ...
- 【Ubuntu】安装OpenSSH启用远程连接
[Ubuntu]安装OpenSSH启用远程连接 零.安装软件 使用如下代码安装OpenSSH服务端: sudo apt install openssh-server 壹.启动服务 使用如下代码启动Op ...
- 【手机】三星手机刷机解决SecSetupWizard已停止
三星手机恢复出厂设置之后,出现SecSetupWizard已停止的解决方案 零.问题 我手上有一部同学给的三星 GT-S6812I,这几天搞了张新卡,多余出的卡就放到这个手机上玩去了.因为是获取了ro ...
- Git 覆盖刚刚 commit 的 message
场景重现 通常噼里啪啦键盘一段猛搓后(写代码啊),然后会 git add . git commit -m "modify semo" # 注意上面 semo 应该是 some,发现 ...
- udl(Universal Data Link)通用数据连接文件
新建文本文档 更改后缀名为.udl(注意小点) 然后打开运行 配置并测试 改回后缀名.txt(有个小点哦) 打开就是了