BZOJ4561 JLoi2016 圆的异或并


Description

在平面直角坐标系中给定N个圆。已知这些圆两两没有交点,即两圆的关系只存在相离和包含。求这些圆的异或面积并。异或面积并为:当一片区域在奇数个圆内则计算其面积,当一片区域在偶数个圆内则不考虑。

Input

第一行包含一个正整数N,代表圆的个数。接下来N行,每行3个非负整数x,y,r,表示一个圆心在(x,y),半径为r的圆。保证|x|,|y|,≤10^8,r>0,N<=200000

Output

仅一行一个整数,表示所有圆的异或面积并除以圆周率Pi的结果。

Sample Input

2

0 0 1

0 0 2

Sample Output

3


还是挺好的一道题吧,但是考场上没有做出来啊

什么鬼畜扫描线


首先我们发现如果考虑一下容斥,嵌套起来的圆是加减加减这样的

也就是说一个圆的面积应该加上还是减去只和包住它且最小的圆有关系

然后我们考虑一个圆最左边的一个节点(x,y)" role="presentation" style="position: relative;">(x,y)(x,y),如果另一个圆包含了这个圆那么在最左边的时候一定存在(x,y1)" role="presentation" style="position: relative;">(x,y1)(x,y1)和(x,y2)" role="presentation" style="position: relative;">(x,y2)(x,y2)满足y1&lt;y&lt;y2" role="presentation" style="position: relative;">y1<y<y2y1<y<y2

然后如果两个圆的关系是相离,一定存在(x,y1)" role="presentation" style="position: relative;">(x,y1)(x,y1)和(x,y2)" role="presentation" style="position: relative;">(x,y2)(x,y2)满足y1&lt;=y2&lt;y" role="presentation" style="position: relative;">y1<=y2<yy1<=y2<y或者y&lt;y1&lt;=y2" role="presentation" style="position: relative;">y<y1<=y2y<y1<=y2

然后我们只需要用一种支持查询前驱后继的数据结构来维护到一个圆的起始位置的时候恰好比它y大的那个圆是什么,用括号序列的形式来理解一下,如果方向相同就是包含,否则就是相离

然后扫描线扫过去


#include<bits/stdc++.h>
using namespace std;
#define N 200010
#define INF 0x3f3f3f3f
#define pi pair<int,int>
struct Circle{int x,y,r;}c[N];
struct Node{int x,id,typ;}p[N<<1];
struct Point{int id,typ;};
long long pow2(int x){return 1ll*x*x;}
int nowx;
bool operator < (const Point &x,const Point &y){
double yx=(double)c[x.id].y+(double)x.typ*(double)sqrt(pow2(c[x.id].r)-pow2(c[x.id].x-nowx));
double yy=(double)c[y.id].y+(double)y.typ*(double)sqrt(pow2(c[y.id].r)-pow2(c[y.id].x-nowx));
if(yx==yy)return x.typ<y.typ;
return yx<yy;
}
bool cmp(Node a,Node b){return a.x<b.x;}
int n,tot=0,vis[N];
set<Point> s;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%d%d",&c[i].x,&c[i].y,&c[i].r);
p[++tot]=(Node){c[i].x-c[i].r,i,1};
p[++tot]=(Node){c[i].x+c[i].r,i,-1};
}
sort(p+1,p+tot+1,cmp);
for(int i=1;i<=tot;i++){
nowx=p[i].x;
if(p[i].typ==1){
set<Point>::iterator it;
it=s.upper_bound((Point){p[i].id,1});
if(it==s.end())vis[p[i].id]=1;
else{
if(it->typ==1)vis[p[i].id]=-vis[it->id];
else vis[p[i].id]=vis[it->id];
}
s.insert((Point){p[i].id,1});
s.insert((Point){p[i].id,-1});
}else{
s.erase((Point){p[i].id,1});
s.erase((Point){p[i].id,-1});
}
}
long long ans=0;
for(int i=1;i<=n;i++)ans+=pow2(c[i].r)*vis[i];
printf("%lld",ans);
return 0;
}

BZOJ4561 JLoi2016 圆的异或并 【扫描线】【set】*的更多相关文章

  1. [BZOJ4561][JLOI2016]圆的异或并(扫描线)

    考虑任何一条垂直于x轴的直线,由于圆不交,所以这条直线上的圆弧构成形似括号序列的样子,且直线移动时圆之间的相对位置不变. 将每个圆拆成两边,左端加右端删.每次加圆时考虑它外面最内层的括号属于谁.用se ...

  2. 【BZOJ4561】[JLoi2016]圆的异或并 扫描线

    [BZOJ4561][JLoi2016]圆的异或并 Description 在平面直角坐标系中给定N个圆.已知这些圆两两没有交点,即两圆的关系只存在相离和包含.求这些圆的异或面积并.异或面积并为:当一 ...

  3. bzoj4561: [JLoi2016]圆的异或并 圆的扫描线

    地址:http://www.lydsy.com/JudgeOnline/problem.php?id=4561 题目: 4561: [JLoi2016]圆的异或并 Time Limit: 30 Sec ...

  4. bzoj4561: [JLoi2016]圆的异或并

    Description 在平面直角坐标系中给定N个圆.已知这些圆两两没有交点,即两圆的关系只存在相离和包含.求这些圆的异或面 积并.异或面积并为:当一片区域在奇数个圆内则计算其面积,当一片区域在偶数个 ...

  5. BZOJ 4561 [JLoi2016]圆的异或并 ——扫描线

    扫描线的应用. 扫描线就是用数据结构维护一个相对的顺序不变,带修改的东西. 通常只用于一次询问的情况. 抽象的看做一条垂直于x轴直线从左向右扫过去. 这道题目要求求出所有圆的异或并. 所以我们可以求出 ...

  6. BZOJ4561 JLOI2016圆的异或并(扫描线+平衡树)

    考虑一条扫描线从左到右扫过这些圆.观察某一时刻直线与这些圆的交点,可以发现构成一个类似括号序列的东西,括号的包含关系与圆的包含关系是相同的.并且当扫描线逐渐移动时,括号间的相对顺序不变.于是考虑用se ...

  7. BZOJ4561: [JLoi2016]圆的异或并 计算几何+treap

    因为本题保证两圆之间只有相包含或相离(不用担心两圆重合 因为我没有RE) 所以每个圆之间的相对位置是确定的  也就是可以按极角排序的, 所以可以按横坐标排序后 扫描同时用treap维护加圆删圆(即遇到 ...

  8. BZOJ 4561: [JLoi2016]圆的异或并 扫描线 + set

    看题解看了半天...... Code: #include<bits/stdc++.h> #define maxn 200010 #define ll long long using nam ...

  9. 【BZOJ-4561】圆的异或并 set + 扫描线

    4561: [JLoi2016]圆的异或并 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 254  Solved: 118[Submit][Statu ...

随机推荐

  1. kotlin 记录(已弃坑)

    kotlin 有些是转载内容 使用nullable值以及空值检测 引用或函数返回值如果可能为null值,则必须显式标记nullable. (在类型后面跟一个问号表示这个对象可能为空,跟两个感叹号表示这 ...

  2. gcc编译出错---make[5]: *** [s-attrtab] Killed

    内存不足导致的编译出错,解决方法是增加swapfile. root@ubuntu:home# swapon -s Filename    Type            Size    Used    ...

  3. [转载]Eclipse的常用快捷键

    常用的快捷键 ctrl+1:快速修复错误 ctrl+shift+L :查看快捷键 alt+?或alt+/:自动补全代码或者提示代码 ctrl+o:快速outline视图 ctrl+shift+r:打开 ...

  4. 《Think in Java》(十一)持有对象

    Java 中的持有对象就是容器啦,看完这一章粗略的了解了 Java 中的容器框架以及常用实现!但是容器框架中的接口以及实现类有好多,下午还得好好看看第 17 章--容器深入研究以及 Java 官方的文 ...

  5. 【程序员笔试面试必会——排序②】Python实现 计数排序、基数排序

    一.计数排序 概要: 时间复杂度O(n),空间复杂度O(k),k是输入序列的值的范围(最大值-最小值),是稳定的.计数排序一般用于已知输入值的范围相对较小,比如给公司员工的身高体重信息排序. 思路: ...

  6. 百度地图API学习总结

    常用技术   1.创建地图: var map = new BMap.Map("divid"); 2.创建坐标点:var point = new BMap.Point("经 ...

  7. Java获取未知类型对象的属性

    获取未知类型对象的属性通常有两种方式: 一是通过自定义注解的方式,通过获取被注解的属性从而获取属性的值,这种方式也是Spring参数注入的重要实现手段 二是通过反射获取属性的名称,通过属性名从而获取属 ...

  8. 08day03

    一.eclipse的使用 可能是全宇宙最好用的IDE debug 查看执行过程 查看源码 二.模块的常用方法 __name__ __file__ __doc__ 三.函数 参数 参数默认值 可变参数 ...

  9. Nginx启动/重启失败

    解决方案: Nginx启动或重启失败,一般是因为配置文件出错了,我们可以使用nginx -t方法查看配置文件出错的地方.也可以通过查看Nginx日志文件定位到Nginx重启失败的原因,Nginx日志文 ...

  10. label技巧

    问题描述: 一般都用label的for属性指定label的点击范围: <label for="male"><input type="radio" ...