bzoj 4561: [JLoi2016]圆的异或并(扫描线+set)
来源:互联网 发布:数控线切割编程软件 编辑:程序博客网 时间:2024/06/05 15:32
4561: [JLoi2016]圆的异或并
Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 715 Solved: 277
[Submit][Status][Discuss]
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-r和x+r)
之后从左到右扫描,扫到一个圆就看它上面最近的一个圆是正贡献还是负贡献,具体看下图
其中当遍历到图中第二小的那个圆的左端时
很显然它上面最靠近它的圆面积是正的,
但是你首先遇到的会是B点,而B点在大圆的下方,所以可知当前小圆面积也是正的
计算完之后将该圆插入
……
同理遍历到图中最小的圆时,
虽然它最上面的最靠近它的圆面积也是正的,但竖线交点那个点在大圆的上方,所以面积为负
……
当遍历到图中第二小的那个圆的右端时,说明整个圆已经没有意义了,删除该圆,其它同理
可以用set维护,用set查询上面最靠近的圆
#include<stdio.h>#include<set>#include<math.h>#include<algorithm>using namespace std;#define LL long longtypedef struct Res{int x, y, r;int t, val, id;}Circle;Circle s[600005], c[300005], temp;typedef struct Pset{int id, t, val;bool operator < (const Pset &b) const{if(id==0)return 1;else if(b.id==0)return 0;else if(id==b.id){if(t>b.t)return 1;return 0;}else{if(c[id].y+t*sqrt((LL)c[id].r*c[id].r-(LL)(temp.x-c[id].x)*(temp.x-c[id].x))>c[b.id].y+b.t*sqrt((LL)c[b.id].r*c[b.id].r-(LL)(temp.x-c[b.id].x)*(temp.x-c[b.id].x)))return 1;return 0;}}}Pset;Pset now;set<Pset> st;bool comp(Circle a, Circle b){if(a.x<b.x || a.x==b.x && a.t<b.t || a.x==b.x && a.t==b.t && a.t*a.r>b.t*b.r)return 1;return 0;}int main(void){LL ans = 0;set<Pset>::iterator it;int cnt, n, i;scanf("%d", &n);cnt = 0;for(i=1;i<=n;i++){scanf("%d%d%d", &c[i].x, &c[i].y, &c[i].r);s[++cnt].x = c[i].x-c[i].r, s[cnt].y = c[i].y, s[cnt].t = 1, s[cnt].r = c[i].r, s[cnt].id = i;s[++cnt].x = c[i].x+c[i].r, s[cnt].y = c[i].y, s[cnt].t = -1, s[cnt].r = c[i].r, s[cnt].id = i;}n = cnt;sort(s+1, s+n+1, comp);now.id = 0, now.val = -1, now.t = 1;st.insert(now);for(i=1;i<=n;i++){if(s[i].t==1){temp = s[i];now.id = s[i].id;now.t = 1;it = --st.upper_bound(now);if((*it).t==1)now.val = -(*it).val;elsenow.val = (*it).val;s[i].val = now.val;ans += (LL)now.val*temp.r*temp.r;st.insert(now);now.t = -1;st.insert(now);}else{now.id = s[i].id;now.t = 1;st.erase(now);now.t = -1;st.erase(now);}}printf("%lld\n", ans);return 0;}/*30 0 40 2 20 -2 2*/
阅读全文
1 0
- bzoj 4561: [JLoi2016]圆的异或并(扫描线+set)
- [扫描线 set] BZOJ 4561 [JLoi2016]圆的异或并
- 【bzoj4561】【JLOI2016】【圆的异或并】【扫描线+set】
- bzoj 4561: [JLoi2016]圆的异或并 (计算几何+扫描线+splay)
- BZOJ 4561 [JLoi2016]圆的异或并
- [BZOJ4561][JLoi2016]圆的异或并(扫描线+splay)
- 4561: [JLoi2016]圆的异或并
- 4561 [JLoi2016] 圆的异或并
- BZOJ4561 [JLoi2016]圆的异或并
- [JLOI2016] 圆的异或并
- BZOJ4561: [JLoi2016]圆的异或并
- bzoj4561【JLOI2016】圆的异或并
- 【BZOJ 4561】【JLOI 2016】圆的异或并
- BZOJ 4558 [JLoi2016] 方
- BZOJ 4636: 蒟蒻的数列 线段树/扫描线 set
- BZOJ 4557: [JLoi2016]侦察守卫
- BZOJ 4557 [JLoi2016]侦察守卫
- BZOJ 4560 [JLoi2016]字符串覆盖
- spring和hibernate关联使用
- gb2312编码
- 【算法与数据结构】KMP算法
- 我对前端开发的简单认识01
- codeforces-375D-树上莫队
- bzoj 4561: [JLoi2016]圆的异或并(扫描线+set)
- android ble notify
- Linux 利用yum源安装php7.0+nginx
- C语言学习笔记(十)---又是一些刷题记录
- java的垃圾回收机制
- Shiro的MD5加密
- 1003. 我要通过
- 常见C++语句解析之printf(陆续补充)
- 【起点】我的第一篇博客!