【BZOJ4561】[JLoi2016]圆的异或并

传送门

把圆拆成上下两个圆弧,因为不存在相交关系,圆弧直接的上下关系是不变的。

用set维护这些圆弧,插入的时候upper_bound一下,如果找到的是上圆弧,就是我外面的第一个圆,否则我外面的第一个圆就是这个下圆弧外面的第一个圆。

//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
#include<set>
#define For(i,a,b) for(int i=(a);i<=(b);i++)
#define Rep(i,a,b) for(int i=(a);i>=(b);i--)
const int N=400007;
typedef long long LL;
typedef double db;
using namespace std;
int n,cnt,f[N];
db x[N],y[N],r[N],now;

template<typename T>void read(T &x)  {
    char ch=getchar(); x=0; T f=1;
    while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    if(ch=='-') f=-1,ch=getchar();
    for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}

struct node {
    int id,f;
    node(){}
    node(int id,int f):id(id),f(f){}
    friend bool operator <(const node&A,const node&B) {
        return x[A.id]+A.f*r[A.id]<x[B.id]+B.f*r[B.id];
    }
}q[N];

struct bow {
    int id,f;
    bow(){}
    bow(int id,int f):id(id),f(f){}
};

bool operator <(const bow&A,const bow&B) {
    db y1=(db)y[A.id]+(db)A.f*sqrt(r[A.id]*r[A.id]-(now-x[A.id])*(now-x[A.id]));
    db y2=(db)y[B.id]+(db)B.f*sqrt(r[B.id]*r[B.id]-(now-x[B.id])*(now-x[B.id]));
    return y1==y2?A.f<B.f:y1<y2;
}

set<bow>s;
#define IT set<bow>::iterator

//#define DEBUG
int main() {
#ifdef DEBUG
    freopen("4561.in","r",stdin);
    freopen("4561.out","w",stdout);
#endif
    read(n);
    For(i,1,n) { read(x[i]); read(y[i]); read(r[i]); q[++cnt]=node(i,-1); q[++cnt]=node(i,1); }
    sort(q+1,q+cnt+1);
    For(i,1,cnt) {
        now=x[q[i].id]+q[i].f*r[q[i].id];
        if(q[i].f==-1) {
            IT it=s.upper_bound(bow(q[i].id,1));
            if(it!=s.end()) { 
                bow tp=*it;
                if(tp.f==-1) f[q[i].id]=f[tp.id];
                else f[q[i].id]=-f[tp.id];
            }
            else f[q[i].id]=1;
            s.insert(bow(q[i].id,1)); s.insert(bow(q[i].id,-1));  
        }
        else s.erase(bow(q[i].id,1)),s.erase(bow(q[i].id,-1)) ;
    }
    db ans=0;
    For(i,1,n) 
        ans+=r[i]*r[i]*f[i];
    printf("%lld\n",(LL)ans);
    return 0;
}
/*
5
-153 -765 50
-51 -765 50
0 867 50
0 969 50
0 969 47
*/
View Code

 

posted @ 2018-03-27 15:46  啊宸  阅读(278)  评论(0编辑  收藏  举报