• 圆的异或并


    bzoj 4561 圆的异或并

    题意

    在平面直角坐标系中给定(N)个圆。已知这些圆两两没有交点,即两圆的关系只存在相离和包含。求这些圆的异或面
    积并。异或面积并为:当一片区域在奇数个圆内则计算其面积,当一片区域在偶数个圆内则不考虑。

    解法

    这个很简单

    因为圆两两不相交,所以其相对位置不变,所以我们将其拆为两个半圆弧,当我们碰到左端点的时候,就加入这两个圆弧,碰到右端点的时候,就将他们删去。然后我们从左到右扫描,找出当前这个圆的前驱,若他为上圆弧,则当前圆为其儿子,否则为其兄弟。这样我们就将圆变为了一个树形图,其中深度为奇数的贡献为正,否则为负。

    代码如下:

    注意:!!!!

    1. 如果set重载小于号的时候,不定义完全,会WA。我就错了几遍
    2. T一定要为当前的x,不然会WA。
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <set>
    #define INF 2139062143
    #define MAX 0x7ffffffffffffff
    #define del(a,b) memset(a,b,sizeof(a))
    #define Rint register int
    using namespace std;
    typedef long long ll;
    template<typename T>
    inline void read(T&x)
    {
        x=0;T k=1;char c=getchar();
        while(!isdigit(c)){if(c=='-')k=-1;c=getchar();}
        while(isdigit(c)){x=x*10+c-'0';c=getchar();}x*=k;
    }
    const int maxn=200000+5;
    double T;
    struct cir{
    	double x,y,r;
    	cir(double x=0.0,double y=0.0,double r=0.0):x(x),y(y),r(r){}
    	double h(int k){
    		return y + k*sqrt( r*r - (T-x)*(T-x) );
    	}
    }c[maxn];
    struct pic{
    	int num,k,deg;
    	pic(int num=0,int k=0,int deg=0):num(num),k(k),deg(deg){}
    }p[maxn<<1];
    bool operator < (const pic& a,const pic& b){
    	double y1=c[a.num].h(a.k),y2=c[b.num].h(b.k);
    	if(y1!=y2) return y1<y2;
    	return a.k<b.k;
    }
    bool cmp(pic a,pic b){
    	double x1=c[a.num].x-a.k*c[a.num].r;
    	double x2=c[b.num].x-b.k*c[b.num].r;
    	return x1<x2;
    }
    set<pic> s;
    int n;
    int main()
    {
    //	freopen("4561.in","r",stdin);
    //	freopen("4561.out","w",stdout);
    	read(n);
    	for(int i=1;i<=n;i++){
    		scanf("%lf%lf%lf",&c[i].x,&c[i].y,&c[i].r);
    		p[i*2-1]=pic(i,1);
    		p[i*2]=pic(i,-1);
    	}
    	sort(p+1,p+1+2*n,cmp);
    	set<pic>:: iterator it;
    	ll ans=0;
    	int deg;
    	for(int i=1;i<=2*n;i++){
    		T=c[p[i].num].x-p[i].k*c[p[i].num].r;//当前的扫描线位置
    		if(p[i].k==1){
    			it=s.upper_bound(p[i]);
    			if(it==s.end()) deg=1;
    			else{
    				if(it->k==1) deg=it->deg+1;
    				else deg=it->deg;
    			}
    			if(deg&1) ans+=ll(c[p[i].num].r*c[p[i].num].r);
    			else ans-=ll(c[p[i].num].r*c[p[i].num].r);
    			s.insert(pic(p[i].num,1,deg));
    			s.insert(pic(p[i].num,-1,deg));
    		}
    		else{
    			s.erase(pic(p[i].num,1,deg));
    			s.erase(pic(p[i].num,-1,deg));
    		}
    	}
    	printf("%lld",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    Exchange 2013与 Office Web Apps 整合
    SharePoint2013 以其他用户登录和修改AD域用户密码 功能
    sharepoint 2010 自定义页面布局
    sharepoint 2010 记录管理 对象模型
    SharePoint2010 对象模型 关联列表
    在SharePoint Server 2010中更改“我的网站”
    xenapp 6.5 客户端插件第一次安装总是跳到官网
    如何解决在Windows Server 2008 R2 上安装证书服务重启后出现 CertificationAuthority 91错误事件
    在Win7 Hyper-v虚拟机中挂接真实机的声卡
    win8 中如何删除 共享文件夹 用户名和密码
  • 原文地址:https://www.cnblogs.com/mrasd/p/9509279.html
Copyright © 2020-2023  润新知