zoukankan      html  css  js  c++  java
  • BZOJ4561 JLoi2016 圆的异或并 【扫描线】【set】*

    BZOJ4561 JLoi2016 圆的异或并


    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,y),如果另一个圆包含了这个圆那么在最左边的时候一定存在(x,y1)(x,y2)满足y1<y<y2
    然后如果两个圆的关系是相离,一定存在(x,y1)(x,y2)满足y1<=y2<y或者y<y1<=y2
    然后我们只需要用一种支持查询前驱后继的数据结构来维护到一个圆的起始位置的时候恰好比它y大的那个圆是什么,用括号序列的形式来理解一下,如果方向相同就是包含,否则就是相离

    然后扫描线扫过去


    #include<bits/stdc++.h>
    using namespace std;
    #define N 200010
    #define INF 0x3f3f3f3f
    #define pi pair<int,int>
    struct Circle{int x,y,r;}c[N];
    struct Node{int x,id,typ;}p[N<<1];
    struct Point{int id,typ;};
    long long pow2(int x){return 1ll*x*x;}
    int nowx;
    bool operator < (const Point &x,const Point &y){
        double yx=(double)c[x.id].y+(double)x.typ*(double)sqrt(pow2(c[x.id].r)-pow2(c[x.id].x-nowx));
        double yy=(double)c[y.id].y+(double)y.typ*(double)sqrt(pow2(c[y.id].r)-pow2(c[y.id].x-nowx));
        if(yx==yy)return x.typ<y.typ;
        return yx<yy;
    }
    bool cmp(Node a,Node b){return a.x<b.x;}
    int n,tot=0,vis[N];
    set<Point> s;
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d%d%d",&c[i].x,&c[i].y,&c[i].r);
            p[++tot]=(Node){c[i].x-c[i].r,i,1};
            p[++tot]=(Node){c[i].x+c[i].r,i,-1};
        }
        sort(p+1,p+tot+1,cmp);
        for(int i=1;i<=tot;i++){
            nowx=p[i].x;
            if(p[i].typ==1){
                set<Point>::iterator it;
                it=s.upper_bound((Point){p[i].id,1});
                if(it==s.end())vis[p[i].id]=1;
                else{
                    if(it->typ==1)vis[p[i].id]=-vis[it->id];
                    else vis[p[i].id]=vis[it->id];
                }
                s.insert((Point){p[i].id,1});
                s.insert((Point){p[i].id,-1});
            }else{
                s.erase((Point){p[i].id,1});
                s.erase((Point){p[i].id,-1});
            }
        }
        long long ans=0;
        for(int i=1;i<=n;i++)ans+=pow2(c[i].r)*vis[i];
        printf("%lld",ans);
        return 0;
    }
  • 相关阅读:
    统计字符的有效字数
    Ubuntu Wifi网络连接不上或经常断网
    Git实战指南----跟着haibiscuit学Git(第十一篇)
    Git实战指南----跟着haibiscuit学Git(第十篇)
    Git实战指南----跟着haibiscuit学Git(第九篇)
    Git实战指南----跟着haibiscuit学Git(第八篇)
    Git实战指南----跟着haibiscuit学Git(第七篇)
    Git实战指南----跟着haibiscuit学Git(第六篇)
    linux之网络命令
    Ceph实战入门之安部署篇
  • 原文地址:https://www.cnblogs.com/dream-maker-yk/p/9676282.html
Copyright © 2011-2022 走看看