覆盖的面积 - HDU 1255 扫描线 重复两次的面积

来源:互联网 发布:盘古数据科技有限公司 编辑:程序博客网 时间:2024/06/08 06:37

覆盖的面积

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3841    Accepted Submission(s): 1887


Problem Description
给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.


 

Input
输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=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
 

题意:计算重复两次以上的面积。

思路:扫描线。tree[o].sum[i]表示节点o所表示的范围内被覆盖次数至少为i的面积有多少,然后向上返回,这样可以降低复杂度。

AC代码如下:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;struct node{    int l,r,lazy;    double sum[3];}tree[8010];struct node2{    int l,r,f;    double h;}line[2010];bool cmp(node2 a,node2 b){    return a.h<b.h;}double p[2010],sum[2010],x1[1010],y1[1010],x2[1010],y2[1010];int n,m;void build(int o,int l,int r){    tree[o].l=l;tree[o].r=r;    tree[o].lazy=0;    tree[o].sum[1]=tree[o].sum[2]=0;    tree[o].sum[0]=sum[tree[o].r]-sum[tree[o].l-1];    if(l==r)      return;    int mi=(l+r)/2;    build(o<<1,l,mi);    build(o<<1|1,mi+1,r);}void solve(int o){    if(tree[o].l==tree[o].r)    {        int i;        for(i=1;i<=min(2,tree[o].lazy);i++)           tree[o].sum[i]=tree[o].sum[0];        for(;i<=2;i++)           tree[o].sum[i]=0;        return;    }    if(tree[o].lazy>=2)    {        tree[o].sum[2]=tree[o].sum[1]=tree[o].sum[0];    }    else if(tree[o].lazy==1)    {        tree[o].sum[2]=tree[o<<1].sum[1]+tree[o<<1|1].sum[1];        tree[o].sum[1]=tree[o].sum[0];    }    else if(tree[o].lazy==0)    {        tree[o].sum[2]=tree[o<<1].sum[2]+tree[o<<1|1].sum[2];        tree[o].sum[1]=tree[o<<1].sum[1]+tree[o<<1|1].sum[1];    }}void update(int o,int l,int r,int f){    if(tree[o].l==l && tree[o].r==r && tree[o].lazy+f>=0)    {        tree[o].lazy+=f;        solve(o);        return;    }    int mi=(tree[o].l+tree[o].r)/2;    if(r<=mi)      update(o<<1,l,r,f);    else if(l>mi)      update(o<<1|1,l,r,f);    else    {        update(o<<1,l,mi,f);        update(o<<1|1,mi+1,r,f);    }    solve(o);}int find(double f){    int l=0,r=m,mi;    while(l<r)    {        mi=(l+r)/2;        if(p[mi]<f)          l=mi+1;        else          r=mi;    }    return l;}int main(){    int T,t,i,j,k,l,r;    double ans;    scanf("%d",&T);    for(t=1;t<=T;t++)    {        scanf("%d",&n);        for(i=1;i<=n;i++)        {            scanf("%lf%lf%lf%lf",&x1[i],&y1[i],&x2[i],&y2[i]);            p[i*2-1]=x1[i];            p[i*2]=x2[i];        }        sort(p+1,p+1+n*2);        p[0]=-1;        m=-1;        for(i=1;i<=n*2;i++)           if(p[i]!=p[i-1])             p[++m]=p[i];        for(i=1;i<=m;i++)           sum[i]=sum[i-1]+p[i]-p[i-1];        for(i=1;i<=n;i++)        {            l=find(x1[i])+1;r=find(x2[i]);            line[i*2-1].l=l;line[i*2-1].r=r;line[i*2-1].f=1;line[i*2-1].h=y1[i];            line[i*2].l=l;line[i*2].r=r;line[i*2].f=-1;line[i*2].h=y2[i];        }        sort(line+1,line+1+n*2,cmp);        build(1,1,m);        ans=0;        for(i=1;i<n*2;i++)        {            update(1,line[i].l,line[i].r,line[i].f);            ans+=tree[1].sum[2]*(line[i+1].h-line[i].h);        }        printf("%.2f\n",ans);    }}



0 0
原创粉丝点击