在平面直角坐标系中给定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(左边),去找这个圆的“上面的第一个半圆Cir”,若Cir是上半圆的话,则X被其包含,否则无。                     然后把圆X加入数据结构中。

扫描到一个圆X(右边),则把圆X从数据结构中删除。

对于当前扫描线里的圆(保存在数据结构里的那些),排序是根据直线与圆的交点的纵坐标排序得到:

下面左图,B上面第一个圆是A,因为3上面第一个点是2。而2代表下半圆,说明无圆包含B。

下图右图,B上面第一个圆是A,因为3上面第一个点是1。而1代表上半圆,说明第一个包含B的是A。(可能A还被其他圆包含,即B<A<...)

简单证明划分圆来解决的可行性:

由于圆之间不相交,所以我们用平行Y轴是直线去扫描的时候(从左向右),直线与圆产生一些交点。

易得:这些圆中,一个圆与直线的两个交点与其他圆的两个交点不交叉。即一对交点“属于哪个圆”这个属性“相离”或者“包含”,不会“交叉”,如下:

如左图:A圆与直线交点1,2,B圆与直线交点3,4。二圆相离,所以(1,2),(3,4)。

如右图:A圆与直线交点1,2,B圆与直线交点3,4。二圆包含。所以(1,(3,4)2)。

不会出现下图中的(1,(3,2)4)

因此,一个圆X被圆Y包含,要求最内层的Y,只需要在这条线上找X与直线的交点a上面的第一个“下半圆交点”即可。

-----------------------上面是简单证明,下面是整正题--------------------------

数据结构用于查找大于等于a的数,可以是set,线段树,判平衡树等。

这里是练习平衡树,但是为了保险,先写了下set,不然直接写splay找错很麻烦。

待续。。。。

#include<set>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
const int maxn=;
struct cir{
ll x,y,r;
cir(){}
cir(ll xx,ll yy,ll rr):x(xx),y(yy),r(rr){}
}c[maxn];
struct ins{
int x,opt,id;
ins(){}
ins(int xx,int oo,int ii):x(xx),opt(oo),id(ii){}
}w[maxn<<];=
ll Lx,sig[maxn]; set<ins>s;
ll cal(ll x) { return x*x; }
bool cmp(ins a,ins b){ return a.x<b.x; }
bool operator <(ins a,ins b){ double y1=c[a.id].y+a.opt*sqrt(cal(c[a.id].r)-cal(c[a.id].x-Lx));
double y2=c[b.id].y+b.opt*sqrt(cal(c[b.id].r)-cal(c[b.id].x-Lx));
if(y1==y2) return a.opt<b.opt; //当一个圆的左顶点刚好在LX线上?
return y1<y2;
}
int main()
{
int N; scanf("%d",&N);
for(int i=;i<=N;i++){
scanf("%lld%lld%lld",&c[i].x,&c[i].y,&c[i].r);
w[(i<<)-]=ins(c[i].x-c[i].r,,i);
w[i<<]=ins(c[i].x+c[i].r,-,i);
}
sort(w+,w+(N<<)+,cmp);
for(int i=;i<=(N<<);i++){
Lx=w[i].x;
if(w[i].opt==){//左,加圆 set<ins>::iterator it;
it=s.upper_bound(ins(,,w[i].id));
if(it==s.end()) sig[w[i].id]=;
else{
if((*it).opt==-) sig[w[i].id]=sig[(*it).id];
else sig[w[i].id]=-sig[(*it).id];
}
s.insert(ins(,,w[i].id));
s.insert(ins(,-,w[i].id));
}
else {
s.erase(ins(,,w[i].id));
s.erase(ins(,-,w[i].id));
}
}
ll ans=;
for(int i=;i<=N;i++) ans+=sig[i]*cal(c[i].r);
printf("%lld\n",ans);
return ;
}

BZOJ4561:圆的异或并(扫描线+set||splay||线段树)的更多相关文章

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

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

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

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

  3. 线段树(单标记+离散化+扫描线+双标记)+zkw线段树+权值线段树+主席树及一些例题

    “队列进出图上的方向 线段树区间修改求出总量 可持久留下的迹象 我们 俯身欣赏” ----<膜你抄>     线段树很早就会写了,但一直没有总结,所以偶尔重写又会懵逼,所以还是要总结一下. ...

  4. P5283 [十二省联考2019]异或粽子 可持久化01Trie+线段树

    $ \color{#0066ff}{ 题目描述 }$ 小粽是一个喜欢吃粽子的好孩子.今天她在家里自己做起了粽子. 小粽面前有 \(n\) 种互不相同的粽子馅儿,小粽将它们摆放为了一排,并从左至右编号为 ...

  5. [CERC2017]Intrinsic Interval——扫描线+转化思想+线段树

    [CERC2017]Intrinsic Interval https://www.luogu.org/blog/ywycasm/solution-p4747# 这种“好的区间”,见得还是比较多的了. ...

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

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

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

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

  8. CodeForces 781E Andryusha and Nervous Barriers 线段树 扫描线

    题意: 有一个\(h \times w\)的矩形,其中有\(n\)个水平的障碍.从上往下扔一个小球,遇到障碍后会分裂成两个,分别从障碍的两边继续往下落. 如果从太高的地方落下来,障碍会消失. 问从每一 ...

  9. 【BZOJ2161】布娃娃 扫描线+线段树

    [BZOJ2161]布娃娃 Description 小时候的雨荨非常听话,是父母眼中的好孩子.在学校是老师的左右手,同学的好榜样.后来她成为艾利斯顿第二代考神,这和小时候培养的良好素质是分不开的.雨荨 ...

随机推荐

  1. 洛谷P2414 - [NOI2011]阿狸的打字机

    Portal Description 首先给出一个只包含小写字母和'B'.'P'的操作序列\(s_0(|s_0|\leq10^5)\).初始时我们有一个空串\(t\),依次按\(s_0\)的每一位进行 ...

  2. 解决Genymotion运行Android 5.0一直卡在开机界面

    在一些机器,启动genymotion 的android5.0版模拟器时,会卡在启动界面,一直启动不了. 这是因为要求的开启虚拟选项没有打开,在第一次启动时,会有提示,但可能大家没有注意(我也没注意到, ...

  3. mapStruct笔记

    背景 mapStruct 是一个方便对象转换的工具,类似的工具还有 Dozer, BeanUtils. 实现 mapStruct的核心是在编译期生成基于转换规则的 Impl 文件,运行时直接调用 Im ...

  4. [转]android 如何获取第三方app的sha1值

    对于android 应用的sha1值和md5值的获取,如果是我们自己的应用,不论是获取测试的和正式的都是比较方便的.但是如何去获取别人开发的app的sha1和md5呢,并且我们只有apk有没有相关的文 ...

  5. CF821E(多次矩阵快速幂)

    题意: 冈伦从二维平面上(0,0)走到(k,0),(k<=1e18),每次有三个行动方向:右上一格.右方一格.右下一格,问一共有多少种走的方案 限制:每段x都有一个天花板,一共有n段天花板(n& ...

  6. 转:浅谈Linux的内存管理机制

    一 物理内存和虚拟内存          我们知道,直接从物理内存读写数据要比从硬盘读写数据要快的多,因此,我们希望所有数据的读取和写入都在内存完成,而内存是有限的,这样就引出了物理内存与虚拟内存的概 ...

  7. 【Nginx】发送响应

    请求处理完毕后,需要向用户发送http响应,告知客户端Nginx的执行结果.http响应主要包括响应行.响应头部.包体三部分.发送http响应时需要执行发送http头部(发送http头部时也会发送响应 ...

  8. SQL 快速参考

    SQL 快速参考 SQL 语句 语法 AND / OR SELECT column_name(s)FROM table_nameWHERE conditionAND|OR condition ALTE ...

  9. 工作总结 使用html模板发邮件 前面空一大块

    HTML邮件的本质其实是发送了一个html页面.邮件的空白必然是页面的空白,所以你要找到你发送邮件的html模板所在,然后去掉空白即可,如果这是一个公共文件,需要注意你往往用的只是你的部分,很大程度还 ...

  10. Android反复闹钟(每天)的实现

    MainActivity例如以下: package cc.cc; import java.util.Calendar; import java.util.Locale; import android. ...