重叠面积--扫描线 hdu1255 覆盖的面积

来源:互联网 发布:最后的晚餐 知乎 编辑:程序博客网 时间:2024/05/16 08:50
给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.


 

Input
输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N&lt;=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000.

注意:本题的输入数据较多,推荐使用scanf读入数据.
 

Output
对于每组测试数据,请计算出被这些矩形覆盖过至少两次的区域的面积.结果保留两位小数.
 

Sample Input
251 1 4 21 3 3 72 1.5 5 4.53.5 1.25 7.5 46 3 10 730 0 1 11 0 2 12 0 3 1
 

Sample Output
7.630.00
#include<iostream>#include<cstdio>#include<cstring>#include<set>#include<queue>#include<map>#include<vector>#include<algorithm>using namespace std;#define maxn 2222int cnt[maxn<<2];double sum[maxn<<2];double insum[maxn<<2];double xid[maxn];struct Seg{    double l,r,h;    int p;    Seg(){}    Seg(double l, double r, double h, int p):l(l),r(r),h(h),p(p){}    bool operator < (const Seg& a) const    {        return h<a.h;    }}seg[maxn];int found(double x, int l, int r){    int m;    while(l<r)    {        m=(l+r)>>1;        if(xid[m]==x) return m;        if(xid[m]>x) r=m-1;        else l=m+1;    }    return l;}void pushup(int l, int r, int rt){    if(cnt[rt]) sum[rt]=xid[r+1]-xid[l];    else if(l==r) sum[rt]=0;    else sum[rt]=sum[rt<<1]+sum[rt<<1|1];}void inpushup(int l, int r, int rt){    if(cnt[rt]>=2) insum[rt]=xid[r+1]-xid[l];    else if(l==r)  insum[rt]=0;    else if(cnt[rt]==1)  insum[rt]=sum[rt<<1]+sum[rt<<1|1];    else  insum[rt]=insum[rt<<1]+insum[rt<<1|1];}void update(int L, int R, int p, int l, int r, int rt){    if(L<=l && R>=r)    {        cnt[rt]+=p;        pushup(l,r,rt);        inpushup(l,r,rt);        return;    }    int m=(l+r)>>1;    if(L<=m) update(L,R,p,l,m,rt<<1);    if(R>m)  update(L,R,p,m+1,r,rt<<1|1);    pushup(l,r,rt);    inpushup(l,r,rt);}int main(){    int T;    int i,j,k,m,n;    double a,b,c,d;    scanf("%d",&T);    while(T--)    {        scanf("%d",&n);        int m=0;        while(n--)        {            scanf("%lf%lf%lf%lf",&a,&b,&c,&d);            xid[++m]=a;            seg[m]=Seg(a,c,b,1);            xid[++m]=c;            seg[m]=Seg(a,c,d,-1);        }        sort(xid+1,xid+1+m);        sort(seg+1,seg+1+m);        int k= unique(xid+1,xid+1+m)-(xid+1);        memset(cnt,0,sizeof(cnt));        memset(sum,0,sizeof(sum));        memset(insum,0,sizeof(insum));        double ans=0.0;        for(i=1;i<m;i++)        {            int l=found(seg[i].l,1,k);            int r=found(seg[i].r,1,k)-1;            if(l<=r) update(l,r,seg[i].p,1,k,1);            ans+=insum[1]*(seg[i+1].h-seg[i].h);        }        printf("%.2f\n",ans);    }    return 0;}


0 0