BZOJ4561 [JLoi2016]圆的异或并
2016-05-12 18:35
691 查看
这题现场的时候n=30000部分分居然是给暴力的,我分段写的个乱搞40分结果暴力都60分,差评
正解:
首先可知一个圆被奇数个圆套则答案减去其面积,被偶数个套则加上其面积,然后我们维护一个垂直于x轴扫描线,从左向右扫,每个圆拆成加入和删除两个事件,由于圆和圆不相交,所以一个圆可以看成一个括号,整个扫描线上是一个括号序列,而且随扫描线当前x增加括号之间相对顺序不变(扫描线都是某些相对顺序不变,然后维护当前x?)
因为圆和圆不相交,所以加入和删除的时候肯定都是对最内层的括号操作,只会影响到自己,所以我们只需要对扫描线上每个点记录他属于哪个圆(算出当前x下y坐标),是左括号还是右括号和外边套了几层(在新加入括号的时候用这两个算出新加的括号是第几层),然后在加入一对括号的时候查询他外面套了几层更新答案即可
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
using namespace std;
#define MAXN 200010
#define MAXM 1010
#define ll long long
#define INF 1000000000
#define MOD 1000000007
#define eps 1e-8
double nowx;
int X[MAXN],Y[MAXN],R[MAXN];
struct cir{
bool ud;
int bel;
int c;
cir(){
}
cir(int _ud,int _bel,int _c=0){
ud=_ud;
bel=_bel;
c=_c;
}
inline double y(int x){
double re=Y[bel];
if(ud){
re+=sqrt(1.0*R[bel]*R[bel]-1.0*(x-X[bel])*(x-X[bel]));
}else{
re-=sqrt(1.0*R[bel]*R[bel]-1.0*(x-X[bel])*(x-X[bel]));
}
return re;
}
friend bool operator <(cir x,cir y){
return fabs(x.y(nowx)-y.y(nowx))>eps?x.y(nowx)>y.y(nowx):x.ud>y.ud;
}
};
struct evt{
int x;
int v;
friend bool operator <(evt x,evt y){
return x.x<y.x;
}
};
int n;
set<cir>wzh;
evt e[MAXN*2];
int tot;
ll ans;
int main(){
int i;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d%d%d",&X[i],&Y[i],&R[i]);
e[++tot].x=X[i]-R[i];
e[tot].v=i;
e[++tot].x=X[i]+R[i];
e[tot].v=-i;
}
R[0]=INF;
nowx=-INF;
wzh.insert(cir(1,0,-1));
wzh.insert(cir(0,0,-1));
sort(e+1,e+tot+1);
int c;
for(i=1;i<=tot;i++){
nowx=e[i].x;
if(e[i].v>0){
cir t=*wzh.upper_bound(cir(0,e[i].v));
if(t.ud){
c=t.c;
}else{
c=t.c+1;
}
if(c&1){
ans-=(ll)R[e[i].v]*R[e[i].v];
}else{
ans+=(ll)R[e[i].v]*R[e[i].v];
}
wzh.insert(cir(1,e[i].v,c));
wzh.insert(cir(0,e[i].v,c));
}else{
e[i].v=-e[i].v;
wzh.erase(cir(1,e[i].v,c));
wzh.erase(cir(0,e[i].v,c));
}
}
printf("%lld\n",ans);
return 0;
}
/*
*/
正解:
首先可知一个圆被奇数个圆套则答案减去其面积,被偶数个套则加上其面积,然后我们维护一个垂直于x轴扫描线,从左向右扫,每个圆拆成加入和删除两个事件,由于圆和圆不相交,所以一个圆可以看成一个括号,整个扫描线上是一个括号序列,而且随扫描线当前x增加括号之间相对顺序不变(扫描线都是某些相对顺序不变,然后维护当前x?)
因为圆和圆不相交,所以加入和删除的时候肯定都是对最内层的括号操作,只会影响到自己,所以我们只需要对扫描线上每个点记录他属于哪个圆(算出当前x下y坐标),是左括号还是右括号和外边套了几层(在新加入括号的时候用这两个算出新加的括号是第几层),然后在加入一对括号的时候查询他外面套了几层更新答案即可
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
using namespace std;
#define MAXN 200010
#define MAXM 1010
#define ll long long
#define INF 1000000000
#define MOD 1000000007
#define eps 1e-8
double nowx;
int X[MAXN],Y[MAXN],R[MAXN];
struct cir{
bool ud;
int bel;
int c;
cir(){
}
cir(int _ud,int _bel,int _c=0){
ud=_ud;
bel=_bel;
c=_c;
}
inline double y(int x){
double re=Y[bel];
if(ud){
re+=sqrt(1.0*R[bel]*R[bel]-1.0*(x-X[bel])*(x-X[bel]));
}else{
re-=sqrt(1.0*R[bel]*R[bel]-1.0*(x-X[bel])*(x-X[bel]));
}
return re;
}
friend bool operator <(cir x,cir y){
return fabs(x.y(nowx)-y.y(nowx))>eps?x.y(nowx)>y.y(nowx):x.ud>y.ud;
}
};
struct evt{
int x;
int v;
friend bool operator <(evt x,evt y){
return x.x<y.x;
}
};
int n;
set<cir>wzh;
evt e[MAXN*2];
int tot;
ll ans;
int main(){
int i;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d%d%d",&X[i],&Y[i],&R[i]);
e[++tot].x=X[i]-R[i];
e[tot].v=i;
e[++tot].x=X[i]+R[i];
e[tot].v=-i;
}
R[0]=INF;
nowx=-INF;
wzh.insert(cir(1,0,-1));
wzh.insert(cir(0,0,-1));
sort(e+1,e+tot+1);
int c;
for(i=1;i<=tot;i++){
nowx=e[i].x;
if(e[i].v>0){
cir t=*wzh.upper_bound(cir(0,e[i].v));
if(t.ud){
c=t.c;
}else{
c=t.c+1;
}
if(c&1){
ans-=(ll)R[e[i].v]*R[e[i].v];
}else{
ans+=(ll)R[e[i].v]*R[e[i].v];
}
wzh.insert(cir(1,e[i].v,c));
wzh.insert(cir(0,e[i].v,c));
}else{
e[i].v=-e[i].v;
wzh.erase(cir(1,e[i].v,c));
wzh.erase(cir(0,e[i].v,c));
}
}
printf("%lld\n",ans);
return 0;
}
/*
*/
相关文章推荐
- java中的IO流
- 高质量C编程06-函数
- 产生冠军 map 的 应用 .
- 剑指offer之面试题45圆圈中最后剩下的数字
- Unity3D协同程序(Coroutine)
- Python学习总结一:环境搭建及基本使用
- HDU 1195 Open the Lock
- 关于传递参数
- C语言封装线程与日志类
- 将博客搬至CSDN
- codeforces 671C Ultimate Weirdness of an Array 线段树+构造
- UITextView
- MyBatis传入参数为集合 list 数组 map写法
- android自定义attr,obtainStyledAttributes函数的说明
- Node.js 异步编程之 Callback介绍
- Android中的普通对话框、单选对话框、多选对话框、带Icon的对话框、以及自定义Adapter和自定义View对话框详解
- 4000 CSS3 的text-shadow实现立体文字和燃烧文字
- hdu 1241 Oil Deposits(DFS)
- GNU M4 笔记
- C C++编程产生指定范围内的随机数