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

看题解看了半天......

Code:

#include<bits/stdc++.h>
#define maxn 200010 
#define ll long long 
using namespace std;
void setIO(string s)
{
    string in=s+".in"; 
    freopen(in.c_str(),"r",stdin); 
}
struct cir
{
    ll x,y,r; 
}c[maxn]; 
struct use
{
    int p,x,k; 
}q[maxn<<1]; 
set<use>S;     
set<use>::iterator it;  
int n; 
ll temp,g[maxn],ans; 
ll calc(ll x) { return x * x;  }
bool cmp(use a,use b) 
{
    return a.x < b.x; 
} 
bool operator<(use a,use b)
{
    double x = c[a.p].y + a.k * sqrt(calc(c[a.p].r) - calc(temp - c[a.p].x));    
    double y = c[b.p].y + b.k * sqrt(calc(c[b.p].r) - calc(temp - c[b.p].x));
    return x==y ?  a.k<b.k : x < y;     
}
int main()
{
    // setIO("input"); 
    int n; 
    scanf("%d",&n); 
    for(int i=1;i<=n;++i)
    {
        scanf("%lld%lld%lld",&c[i].x,&c[i].y,&c[i].r); 
        q[(i<<1)-1]=use{i,c[i].x-c[i].r,1};     //  上圆弧 
        q[i<<1]={i,c[i].x+c[i].r,-1};           //  下圆弧 
    }
    sort(q+1,q+(n<<1)+1,cmp);                   // 按照横坐标排序
    for(int i=1;i<=(n<<1);++i)
    {
        temp=q[i].x;      
        if(q[i].k==1)
        {
            it=S.upper_bound(use{q[i].p,0,-1});           
            if(it==S.end()) g[q[i].p]=1; 
            else 
            {
                if((*it).k==-1) g[q[i].p]=g[(*it).p]; 
                else 
                {
                    g[q[i].p]=-g[(*it).p]; 
                }
            }
            S.insert(use{q[i].p,0,1}); 
            S.insert(use{q[i].p,0,-1});    
        }
        else
        {
            S.erase(use{q[i].p,0,1}); 
            S.erase(use{q[i].p,0,-1});              
        }
    }
    for(int i=1;i<=n;++i)
    {
        ans += calc(c[i].r) * g[i]; 
    }
    printf("%lld\n",ans);   
    return 0; 
}

  

posted @ 2019-06-19 14:52  EM-LGH  阅读(146)  评论(0编辑  收藏  举报